Bug 524107 - part 1 - pass original value of 'lang' to gfx text code rather than only a 'langGroup' value, to allow language-specific font rendering. r=roc sr=mats
authorJonathan Kew <jfkthame@gmail.com>
Wed, 24 Feb 2010 09:57:44 -0800
changeset 38492 fe3c9f571228d6c9d8c8effc17755c4c4206b84b
parent 38491 639b98ae11a87689ec600d710c630aebef72c34f
child 38493 4c60c40075e932db1ee1e52d6e8c3370b112c72a
push idunknown
push userunknown
push dateunknown
reviewersroc, mats
bugs524107
milestone1.9.3a2pre
Bug 524107 - part 1 - pass original value of 'lang' to gfx text code rather than only a 'langGroup' value, to allow language-specific font rendering. r=roc sr=mats
accessible/src/base/nsTextAttrs.cpp
accessible/src/msaa/nsTextAccessibleWrap.cpp
content/canvas/src/nsCanvasRenderingContext2D.cpp
gfx/public/nsIDeviceContext.h
gfx/public/nsIFontMetrics.h
gfx/public/nsIRenderingContext.h
gfx/src/thebes/nsThebesDeviceContext.cpp
gfx/src/thebes/nsThebesDeviceContext.h
gfx/src/thebes/nsThebesFontMetrics.cpp
gfx/src/thebes/nsThebesFontMetrics.h
gfx/src/thebes/nsThebesRenderingContext.cpp
gfx/src/thebes/nsThebesRenderingContext.h
gfx/thebes/public/gfxFont.h
gfx/thebes/public/gfxPangoFonts.h
gfx/thebes/public/gfxPlatform.h
gfx/thebes/src/gfxFT2Fonts.cpp
gfx/thebes/src/gfxFont.cpp
gfx/thebes/src/gfxPangoFonts.cpp
gfx/thebes/src/gfxPlatform.cpp
gfx/thebes/src/gfxPlatformFontList.cpp
gfx/thebes/src/gfxWindowsFonts.cpp
gfx/thebes/test/gfxFontSelectionTests.h
gfx/thebes/test/gfxTextRunPerfTest.cpp
gfx/thebes/test/gfxWordCacheTest.cpp
intl/locale/public/nsILanguageAtomService.h
intl/locale/src/nsLanguageAtomService.cpp
intl/locale/src/nsLanguageAtomService.h
intl/uconv/src/charsetData.properties
intl/uconv/src/nsCharsetConverterManager.cpp
layout/base/nsLayoutUtils.cpp
layout/base/nsPresContext.cpp
layout/base/nsPresContext.h
layout/generic/nsPageFrame.cpp
layout/generic/nsTextFrameThebes.cpp
layout/mathml/nsMathMLChar.cpp
layout/mathml/nsMathMLmencloseFrame.cpp
layout/mathml/nsMathMLmfencedFrame.cpp
layout/mathml/nsMathMLmfracFrame.cpp
layout/mathml/nsMathMLmmultiscriptsFrame.cpp
layout/mathml/nsMathMLmoFrame.cpp
layout/mathml/nsMathMLmoverFrame.cpp
layout/mathml/nsMathMLmrootFrame.cpp
layout/mathml/nsMathMLmsubsupFrame.cpp
layout/mathml/nsMathMLmtableFrame.cpp
layout/mathml/nsMathMLmunderFrame.cpp
layout/mathml/nsMathMLmunderoverFrame.cpp
layout/style/nsRuleNode.cpp
layout/style/nsStyleStruct.cpp
layout/style/nsStyleStruct.h
layout/svg/base/src/nsSVGGlyphFrame.cpp
--- a/accessible/src/base/nsTextAttrs.cpp
+++ b/accessible/src/base/nsTextAttrs.cpp
@@ -652,17 +652,17 @@ nsFontWeightTextAttr::GetFontWeight(nsIF
   // value of font weight (used font might not have some font weight values).
   nsStyleFont* styleFont =
     (nsStyleFont*)(aFrame->GetStyleDataExternal(eStyleStruct_Font));
 
   gfxUserFontSet *fs = aFrame->PresContext()->GetUserFontSet();
 
   nsCOMPtr<nsIFontMetrics> fm;
   aFrame->PresContext()->DeviceContext()->
-    GetMetricsFor(styleFont->mFont, aFrame->GetStyleVisibility()->mLangGroup,
+    GetMetricsFor(styleFont->mFont, aFrame->GetStyleVisibility()->mLanguage,
                   fs, *getter_AddRefs(fm));
 
   nsCOMPtr<nsIThebesFontMetrics> tfm = do_QueryInterface(fm);
   gfxFontGroup *fontGroup = tfm->GetThebesFontGroup();
   gfxFont *font = fontGroup->GetFontAt(0);
 
   // When there doesn't exist a bold font in the family and so the rendering of
   // a non-bold font face is changed so that the user sees what looks like a
--- a/accessible/src/msaa/nsTextAccessibleWrap.cpp
+++ b/accessible/src/msaa/nsTextAccessibleWrap.cpp
@@ -256,17 +256,17 @@ STDMETHODIMP nsTextAccessibleWrap::get_f
   if (!rc) {
     return E_FAIL;
   }
 
   const nsStyleFont *font = frame->GetStyleFont();
 
   const nsStyleVisibility *visibility = frame->GetStyleVisibility();
 
-  if (NS_FAILED(rc->SetFont(font->mFont, visibility->mLangGroup,
+  if (NS_FAILED(rc->SetFont(font->mFont, visibility->mLanguage,
                             presShell->GetPresContext()->GetUserFontSet()))) {
     return E_FAIL;
   }
 
   nsCOMPtr<nsIDeviceContext> deviceContext;
   rc->GetDeviceContext(*getter_AddRefs(deviceContext));
   if (!deviceContext) {
     return E_FAIL;
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -1927,18 +1927,18 @@ nsCanvasRenderingContext2D::SetFont(cons
         return NS_ERROR_FAILURE;
     }
 
     nsIPresShell* presShell = GetPresShell();
     if (!presShell)
       return NS_ERROR_FAILURE;
     nsIDocument* document = presShell->GetDocument();
 
-    nsCString langGroup;
-    presShell->GetPresContext()->GetLangGroup()->ToUTF8String(langGroup);
+    nsCString language;
+    presShell->GetPresContext()->GetLanguage()->ToUTF8String(language);
 
     nsCOMArray<nsIStyleRule> rules;
 
     nsCOMPtr<nsICSSStyleRule> rule;
     rv = CreateFontStyleRule(font, mCSSParser.get(), document, getter_AddRefs(rule));
     if (NS_FAILED(rv))
         return rv;
 
@@ -1993,17 +1993,17 @@ nsCanvasRenderingContext2D::SetFont(cons
 
     PRBool printerFont = (presShell->GetPresContext()->Type() == nsPresContext::eContext_PrintPreview ||
                           presShell->GetPresContext()->Type() == nsPresContext::eContext_Print);
 
     gfxFontStyle style(fontStyle->mFont.style,
                        fontStyle->mFont.weight,
                        fontStyle->mFont.stretch,
                        NSAppUnitsToFloatPixels(fontSize, aupcp),
-                       langGroup,
+                       language,
                        fontStyle->mFont.sizeAdjust,
                        fontStyle->mFont.systemFont,
                        fontStyle->mFont.familyNameQuirks,
                        printerFont);
 
     CurrentState().fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(fontStyle->mFont.name, &style, presShell->GetPresContext()->GetUserFontSet());
     NS_ASSERTION(CurrentState().fontGroup, "Could not get font group");
     CurrentState().font = font;
--- a/gfx/public/nsIDeviceContext.h
+++ b/gfx/public/nsIDeviceContext.h
@@ -163,20 +163,19 @@ typedef void * nsNativeDeviceContext;
 #ifdef NS_PRINT_PREVIEW
 const PRUint8 kUseAltDCFor_NONE            = 0x00; // Do not use the AltDC for anything
 const PRUint8 kUseAltDCFor_FONTMETRICS     = 0x01; // Use it for only getting the font metrics
 const PRUint8 kUseAltDCFor_CREATERC_REFLOW = 0x02; // Use when creating RenderingContexts for Reflow
 const PRUint8 kUseAltDCFor_CREATERC_PAINT  = 0x04; // Use when creating RenderingContexts for Painting
 const PRUint8 kUseAltDCFor_SURFACE_DIM     = 0x08; // Use it for getting the Surface Dimensions
 #endif
 
-// 40aebd88-a82b-48b0-8a44-be51510064a7
 #define NS_IDEVICE_CONTEXT_IID   \
-{ 0x40aebd88, 0xa82b, 0x48b0, \
-  { 0x8a, 0x44, 0xbe, 0x51, 0x51, 0x00, 0x64, 0xa7 } }
+{ 0x41391E7C, 0x9ED5, 0x4A60, \
+  { 0x88, 0x72, 0x06, 0x15, 0x73, 0xF5, 0x0E, 0xE7 } }
 
   typedef enum {
     eSystemFont_Caption,         // css2
     eSystemFont_Icon,
     eSystemFont_Menu,
     eSystemFont_MessageBox,
     eSystemFont_SmallCaption,
     eSystemFont_StatusBar,
@@ -312,22 +311,22 @@ public:
    * @return error status
    */
   NS_IMETHOD  GetSystemFont(nsSystemFontID aID, nsFont *aFont) const = 0;
 
   /**
    * Get the nsIFontMetrics that describe the properties of
    * an nsFont.
    * @param aFont font description to obtain metrics for
-   * @param aLangGroup the language group of the document
+   * @param aLanguage the language of the document
    * @param aMetrics out parameter for font metrics
    * @param aUserFontSet user font set
    * @return error status
    */
-  NS_IMETHOD  GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
+  NS_IMETHOD  GetMetricsFor(const nsFont& aFont, nsIAtom* aLanguage,
                             gfxUserFontSet* aUserFontSet,
                             nsIFontMetrics*& aMetrics) = 0;
 
   /**
    * Get the nsIFontMetrics that describe the properties of
    * an nsFont.
    * @param aFont font description to obtain metrics for
    * @param aMetrics out parameter for font metrics
--- a/gfx/public/nsIFontMetrics.h
+++ b/gfx/public/nsIFontMetrics.h
@@ -44,18 +44,18 @@
 
 class nsString;
 class nsIDeviceContext;
 class nsIAtom;
 class gfxUserFontSet;
 
 // IID for the nsIFontMetrics interface
 #define NS_IFONT_METRICS_IID   \
-{ 0xc74cb770, 0xa33e, 0x11d1, \
-{ 0xa8, 0x24, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } }
+{ 0x360C5575, 0xF7AC, 0x4079, \
+{ 0xB8, 0xA6, 0x56, 0x91, 0x4B, 0xEA, 0x2A, 0xEA } }
 
 //----------------------------------------------------------------------
 
 /**
  * A native font handle
  */
 typedef void* nsFontHandle;
 
@@ -82,17 +82,17 @@ public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFONT_METRICS_IID)
 
   /**
    * Initialize the font metrics. Call this after creating the font metrics.
    * Font metrics you get from the font cache do NOT need to be initialized
    *
    * @see nsIDeviceContext#GetMetricsFor()
    */
-  NS_IMETHOD  Init(const nsFont& aFont, nsIAtom* aLangGroup,
+  NS_IMETHOD  Init(const nsFont& aFont, nsIAtom* aLanguage,
                    nsIDeviceContext *aContext, gfxUserFontSet *aUserFontSet = nsnull) = 0;
 
   /**
    * Destroy this font metrics. This breaks the association between
    * the font metrics and the device context.
    */
   NS_IMETHOD  Destroy() = 0;
 
@@ -192,19 +192,19 @@ public:
 
   /**
    * Returns the font associated with these metrics. The return value
    * is only defined after Init() has been called.
    */
   const nsFont &Font() { return mFont; }
 
   /**
-   * Returns the language group associated with these metrics
+   * Returns the language associated with these metrics
    */
-  NS_IMETHOD  GetLangGroup(nsIAtom** aLangGroup) = 0;
+  NS_IMETHOD  GetLanguage(nsIAtom** aLanguage) = 0;
 
   /**
    * Returns the font handle associated with these metrics
    */
   NS_IMETHOD  GetFontHandle(nsFontHandle &aHandle) = 0;
 
   /**
    * Returns the average character width
--- a/gfx/public/nsIRenderingContext.h
+++ b/gfx/public/nsIRenderingContext.h
@@ -95,18 +95,18 @@ typedef enum
   nsPenMode_kNone   = 0,
   nsPenMode_kInvert = 1
 } nsPenMode;
 
 
 // IID for the nsIRenderingContext interface
 // 37762dd8-8df0-48cd-a5d6-24573ffdb5b6
 #define NS_IRENDERING_CONTEXT_IID \
-{ 0x37762dd8, 0x8df0, 0x48cd, \
-  { 0xa5, 0xd6, 0x24, 0x57, 0x3f, 0xfd, 0xb5, 0xb6 } }
+{ 0xA553DAB8, 0xD8B3, 0x469F, \
+  { 0x85, 0xC5, 0xD9, 0x4E, 0xBD, 0x65, 0x37, 0x5D } }
 
 //----------------------------------------------------------------------
 
 // RenderingContext interface
 class nsIRenderingContext : public nsISupports
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IRENDERING_CONTEXT_IID)
@@ -198,17 +198,24 @@ public:
    * @return The current forground color of the RenderingContext
    */
   NS_IMETHOD GetColor(nscolor &aColor) const = 0;
 
   /**
    * Sets the font for the RenderingContext
    * @param aFont The font to use in the RenderingContext
    */
-  NS_IMETHOD SetFont(const nsFont& aFont, nsIAtom* aLangGroup,
+  NS_IMETHOD SetFont(const nsFont& aFont, nsIAtom* aLanguage,
+                     gfxUserFontSet *aUserFontSet) = 0;
+
+  /**
+   * Sets the font for the RenderingContext, without language info
+   * @param aFont The font to use in the RenderingContext
+   */
+  NS_IMETHOD SetFont(const nsFont& aFont,
                      gfxUserFontSet *aUserFontSet) = 0;
 
   /**
    * Sets the font for the RenderingContext
    * @param aFontMetric The font metrics representing the
    *        font to use in the RenderingContext
    */
   NS_IMETHOD SetFont(nsIFontMetrics *aFontMetrics) = 0;
--- a/gfx/src/thebes/nsThebesDeviceContext.cpp
+++ b/gfx/src/thebes/nsThebesDeviceContext.cpp
@@ -124,17 +124,17 @@ PRLogModuleInfo* gThebesGFXLog = nsnull;
 
 class nsFontCache
 {
 public:
     nsFontCache();
     ~nsFontCache();
 
     nsresult Init(nsIDeviceContext* aContext);
-    nsresult GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
+    nsresult GetMetricsFor(const nsFont& aFont, nsIAtom* aLanguage,
                            gfxUserFontSet* aUserFontSet,
                            nsIFontMetrics*& aMetrics);
 
     nsresult FontMetricsDeleted(const nsIFontMetrics* aFontMetrics);
     nsresult Compact();
     nsresult Flush();
     nsresult CreateFontMetricsInstance(nsIFontMetrics** fm);
 
@@ -162,31 +162,31 @@ nsFontCache::Init(nsIDeviceContext* aCon
     NS_PRECONDITION(nsnull != aContext, "null ptr");
     // Note: we don't hold a reference to the device context, because it
     // holds a reference to us and we don't want circular references
     mContext = aContext;
     return NS_OK;
 }
 
 nsresult
-nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
+nsFontCache::GetMetricsFor(const nsFont& aFont, nsIAtom* aLanguage,
   gfxUserFontSet* aUserFontSet, nsIFontMetrics*& aMetrics)
 {
     // First check our cache
     // start from the end, which is where we put the most-recent-used element
 
     nsIFontMetrics* fm;
     PRInt32 n = mFontMetrics.Length() - 1;
     for (PRInt32 i = n; i >= 0; --i) {
         fm = mFontMetrics[i];
         nsIThebesFontMetrics* tfm = static_cast<nsIThebesFontMetrics*>(fm);
         if (fm->Font().Equals(aFont) && tfm->GetUserFontSet() == aUserFontSet) {
-            nsCOMPtr<nsIAtom> langGroup;
-            fm->GetLangGroup(getter_AddRefs(langGroup));
-            if (aLangGroup == langGroup.get()) {
+            nsCOMPtr<nsIAtom> language;
+            fm->GetLanguage(getter_AddRefs(language));
+            if (aLanguage == language.get()) {
                 if (i != n) {
                     // promote it to the end of the cache
                     mFontMetrics.RemoveElementAt(i);
                     mFontMetrics.AppendElement(fm);
                 }
                 tfm->GetThebesFontGroup()->UpdateFontList();
                 NS_ADDREF(aMetrics = fm);
                 return NS_OK;
@@ -194,17 +194,17 @@ nsFontCache::GetMetricsFor(const nsFont&
         }
     }
 
     // It's not in the cache. Get font metrics and then cache them.
 
     aMetrics = nsnull;
     nsresult rv = CreateFontMetricsInstance(&fm);
     if (NS_FAILED(rv)) return rv;
-    rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet);
+    rv = fm->Init(aFont, aLanguage, mContext, aUserFontSet);
     if (NS_SUCCEEDED(rv)) {
         // the mFontMetrics list has the "head" at the end, because append
         // is cheaper than insert
         mFontMetrics.AppendElement(fm);
         aMetrics = fm;
         NS_ADDREF(aMetrics);
         return NS_OK;
     }
@@ -213,17 +213,17 @@ nsFontCache::GetMetricsFor(const nsFont&
 
     // One reason why Init() fails is because the system is running out of
     // resources. e.g., on Win95/98 only a very limited number of GDI
     // objects are available. Compact the cache and try again.
 
     Compact();
     rv = CreateFontMetricsInstance(&fm);
     if (NS_FAILED(rv)) return rv;
-    rv = fm->Init(aFont, aLangGroup, mContext, aUserFontSet);
+    rv = fm->Init(aFont, aLanguage, mContext, aUserFontSet);
     if (NS_SUCCEEDED(rv)) {
         mFontMetrics.AppendElement(fm);
         aMetrics = fm;
         NS_ADDREF(aMetrics);
         return NS_OK;
     }
     fm->Destroy();
     NS_RELEASE(fm);
@@ -371,65 +371,66 @@ NS_IMETHODIMP nsThebesDeviceContext::Fon
 {
     if (mFontCache) {
         mFontCache->FontMetricsDeleted(aFontMetrics);
     }
     return NS_OK;
 }
 
 void
-nsThebesDeviceContext::GetLocaleLangGroup(void)
+nsThebesDeviceContext::GetLocaleLanguage(void)
 {
-    if (!mLocaleLangGroup) {
+    if (!mLocaleLanguage) {
         nsCOMPtr<nsILanguageAtomService> langService;
         langService = do_GetService(NS_LANGUAGEATOMSERVICE_CONTRACTID);
         if (langService) {
-            mLocaleLangGroup = langService->GetLocaleLanguageGroup();
+            mLocaleLanguage = langService->GetLocaleLanguage();
         }
-        if (!mLocaleLangGroup) {
-            mLocaleLangGroup = do_GetAtom("x-western");
+        if (!mLocaleLanguage) {
+            mLocaleLanguage = do_GetAtom("x-western");
         }
     }
 }
 
 NS_IMETHODIMP nsThebesDeviceContext::GetMetricsFor(const nsFont& aFont,
-  nsIAtom* aLangGroup, gfxUserFontSet* aUserFontSet, nsIFontMetrics*& aMetrics)
+  nsIAtom* aLanguage, gfxUserFontSet* aUserFontSet, nsIFontMetrics*& aMetrics)
 {
     if (nsnull == mFontCache) {
         nsresult rv = CreateFontCache();
         if (NS_FAILED(rv)) {
             aMetrics = nsnull;
             return rv;
         }
         // XXX temporary fix for performance problem -- erik
-        GetLocaleLangGroup();
+        GetLocaleLanguage();
     }
 
-    // XXX figure out why aLangGroup is NULL sometimes
-    if (!aLangGroup) {
-        aLangGroup = mLocaleLangGroup;
+    // XXX figure out why aLanguage is NULL sometimes
+    //      -> see nsPageFrame.cpp:511
+    if (!aLanguage) {
+        aLanguage = mLocaleLanguage;
     }
 
-    return mFontCache->GetMetricsFor(aFont, aLangGroup, aUserFontSet, aMetrics);
+    return mFontCache->GetMetricsFor(aFont, aLanguage, aUserFontSet, aMetrics);
 }
 
 NS_IMETHODIMP nsThebesDeviceContext::GetMetricsFor(const nsFont& aFont,
                                                    gfxUserFontSet* aUserFontSet,
                                                    nsIFontMetrics*& aMetrics)
 {
     if (nsnull == mFontCache) {
         nsresult rv = CreateFontCache();
         if (NS_FAILED(rv)) {
             aMetrics = nsnull;
             return rv;
         }
         // XXX temporary fix for performance problem -- erik
-        GetLocaleLangGroup();
+        GetLocaleLanguage();
     }
-    return mFontCache->GetMetricsFor(aFont, mLocaleLangGroup, aUserFontSet,
+    return mFontCache->GetMetricsFor(aFont, mLocaleLanguage, aUserFontSet,
                                      aMetrics);
 }
 
 struct FontEnumData {
     FontEnumData(nsIDeviceContext* aDC, nsString& aFaceName)
         : mDC(aDC), mFaceName(aFaceName)
     {}
     nsIDeviceContext* mDC;
--- a/gfx/src/thebes/nsThebesDeviceContext.h
+++ b/gfx/src/thebes/nsThebesDeviceContext.h
@@ -83,17 +83,17 @@ public:
 
     NS_IMETHOD Init(nsIWidget *aWidget);
     NS_IMETHOD InitForPrinting(nsIDeviceContextSpec *aDevSpec);
     NS_IMETHOD CreateRenderingContext(nsIView *aView, nsIRenderingContext *&aContext);
     NS_IMETHOD CreateRenderingContext(nsIWidget *aWidget, nsIRenderingContext *&aContext);
     NS_IMETHOD CreateRenderingContext(nsIRenderingContext *&aContext);
     NS_IMETHOD CreateRenderingContextInstance(nsIRenderingContext *&aContext);
 
-    NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLangGroup,
+    NS_IMETHOD GetMetricsFor(const nsFont& aFont, nsIAtom* aLanguage,
                              gfxUserFontSet* aUserFontSet,
                              nsIFontMetrics*& aMetrics);
     NS_IMETHOD GetMetricsFor(const nsFont& aFont,
                              gfxUserFontSet* aUserFontSet,
                              nsIFontMetrics*& aMetrics);
 
     NS_IMETHOD FirstExistingFont(const nsFont& aFont, nsString& aFaceName);
 
@@ -143,27 +143,27 @@ public:
     HDC GetPrintHDC();
 #endif
 
 protected:
     virtual nsresult CreateFontAliasTable();
     nsresult AliasFont(const nsString& aFont, 
                        const nsString& aAlias, const nsString& aAltAlias,
                        PRBool aForceAlias);
-    void GetLocaleLangGroup(void);
+    void GetLocaleLanguage(void);
     nsresult SetDPI();
     void ComputeClientRectUsingScreen(nsRect *outRect);
     void ComputeFullAreaUsingScreen(nsRect *outRect);
     void FindScreen(nsIScreen **outScreen);
     void CalcPrintingSize();
     void UpdateScaledAppUnits();
 
     PRUint32          mDepth;
     nsFontCache*      mFontCache;
-    nsCOMPtr<nsIAtom> mLocaleLangGroup; // XXX temp fix for performance bug - erik
+    nsCOMPtr<nsIAtom> mLocaleLanguage; // XXX temp fix for performance bug
     nsHashtable*      mFontAliasTable;
     nsIWidget*        mWidget;
 #ifdef NS_DEBUG
     PRBool            mInitialized;
 #endif
 
 private:
     nsCOMPtr<nsIScreenManager> mScreenManager;
--- a/gfx/src/thebes/nsThebesFontMetrics.cpp
+++ b/gfx/src/thebes/nsThebesFontMetrics.cpp
@@ -60,39 +60,37 @@ nsThebesFontMetrics::~nsThebesFontMetric
 {
     if (mDeviceContext)
         mDeviceContext->FontMetricsDeleted(this);
     delete mFontStyle;
     //delete mFontGroup;
 }
 
 NS_IMETHODIMP
-nsThebesFontMetrics::Init(const nsFont& aFont, nsIAtom* aLangGroup,
+nsThebesFontMetrics::Init(const nsFont& aFont, nsIAtom* aLanguage,
                           nsIDeviceContext *aContext, 
                           gfxUserFontSet *aUserFontSet)
 {
     mFont = aFont;
-    mLangGroup = aLangGroup;
+    mLanguage = aLanguage;
     mDeviceContext = (nsThebesDeviceContext*)aContext;
     mP2A = mDeviceContext->AppUnitsPerDevPixel();
     mIsRightToLeft = PR_FALSE;
     mTextRunRTL = PR_FALSE;
 
     gfxFloat size = gfxFloat(aFont.size) / mP2A;
 
-    nsCString langGroup;
-    if (aLangGroup) {
-        const char* lg;
-        mLangGroup->GetUTF8String(&lg);
-        langGroup.Assign(lg);
+    nsCString language;
+    if (aLanguage) {
+        mLanguage->ToUTF8String(language);
     }
 
     PRBool printerFont = mDeviceContext->IsPrinterSurface();
     mFontStyle = new gfxFontStyle(aFont.style, aFont.weight, aFont.stretch,
-                                  size, langGroup,
+                                  size, language,
                                   aFont.sizeAdjust, aFont.systemFont,
                                   aFont.familyNameQuirks,
                                   printerFont);
 
     mFontGroup =
         gfxPlatform::GetPlatform()->CreateFontGroup(aFont.name, mFontStyle, 
                                                     aUserFontSet);
     if (mFontGroup->FontListLength() < 1) 
@@ -242,20 +240,20 @@ nsThebesFontMetrics::GetMaxDescent(nscoo
 NS_IMETHODIMP
 nsThebesFontMetrics::GetMaxAdvance(nscoord &aAdvance)
 {
     aAdvance = CEIL_TO_TWIPS(GetMetrics().maxAdvance);
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsThebesFontMetrics::GetLangGroup(nsIAtom** aLangGroup)
+nsThebesFontMetrics::GetLanguage(nsIAtom** aLanguage)
 {
-    *aLangGroup = mLangGroup;
-    NS_IF_ADDREF(*aLangGroup);
+    *aLanguage = mLanguage;
+    NS_IF_ADDREF(*aLanguage);
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsThebesFontMetrics::GetFontHandle(nsFontHandle &aHandle)
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
--- a/gfx/src/thebes/nsThebesFontMetrics.h
+++ b/gfx/src/thebes/nsThebesFontMetrics.h
@@ -51,17 +51,17 @@
 class nsThebesFontMetrics : public nsIThebesFontMetrics
 {
 public:
     nsThebesFontMetrics();
     virtual ~nsThebesFontMetrics();
 
     NS_DECL_ISUPPORTS
 
-    NS_IMETHOD  Init(const nsFont& aFont, nsIAtom* aLangGroup,
+    NS_IMETHOD  Init(const nsFont& aFont, nsIAtom* aLanguage,
                      nsIDeviceContext *aContext, 
                      gfxUserFontSet *aUserFontSet = nsnull);
     NS_IMETHOD  Destroy();
     NS_IMETHOD  GetXHeight(nscoord& aResult);
     NS_IMETHOD  GetSuperscriptOffset(nscoord& aResult);
     NS_IMETHOD  GetSubscriptOffset(nscoord& aResult);
     NS_IMETHOD  GetStrikeout(nscoord& aOffset, nscoord& aSize);
     NS_IMETHOD  GetUnderline(nscoord& aOffset, nscoord& aSize);
@@ -70,17 +70,17 @@ public:
     NS_IMETHOD  GetExternalLeading(nscoord &aLeading);
     NS_IMETHOD  GetEmHeight(nscoord &aHeight);
     NS_IMETHOD  GetEmAscent(nscoord &aAscent);
     NS_IMETHOD  GetEmDescent(nscoord &aDescent);
     NS_IMETHOD  GetMaxHeight(nscoord &aHeight);
     NS_IMETHOD  GetMaxAscent(nscoord &aAscent);
     NS_IMETHOD  GetMaxDescent(nscoord &aDescent);
     NS_IMETHOD  GetMaxAdvance(nscoord &aAdvance);
-    NS_IMETHOD  GetLangGroup(nsIAtom** aLangGroup);
+    NS_IMETHOD  GetLanguage(nsIAtom** aLanguage);
     NS_IMETHOD  GetFontHandle(nsFontHandle &aHandle);
     NS_IMETHOD  GetAveCharWidth(nscoord& aAveCharWidth);
     NS_IMETHOD  GetSpaceWidth(nscoord& aSpaceCharWidth);
     virtual PRInt32 GetMaxStringLength();
 
 
     virtual nsresult GetWidth(const char* aString, PRUint32 aLength, nscoord& aWidth,
                               nsThebesRenderingContext *aContext);
@@ -186,15 +186,15 @@ protected:
     };
     friend class AutoTextRun;
 
     nsRefPtr<gfxFontGroup> mFontGroup;
     gfxFontStyle *mFontStyle;
 
 private:
     nsThebesDeviceContext *mDeviceContext;
-    nsCOMPtr<nsIAtom> mLangGroup;
+    nsCOMPtr<nsIAtom> mLanguage;
     PRInt32 mP2A;
     PRPackedBool mIsRightToLeft;
     PRPackedBool mTextRunRTL;
 };
 
 #endif /* NSTHEBESFONTMETRICS__H__ */
--- a/gfx/src/thebes/nsThebesRenderingContext.cpp
+++ b/gfx/src/thebes/nsThebesRenderingContext.cpp
@@ -814,23 +814,36 @@ nsThebesRenderingContext::GetRightToLeft
 
 void
 nsThebesRenderingContext::SetTextRunRTL(PRBool aIsRTL)
 {
     mFontMetrics->SetTextRunRTL(aIsRTL);
 }
 
 NS_IMETHODIMP
-nsThebesRenderingContext::SetFont(const nsFont& aFont, nsIAtom* aLangGroup,
+nsThebesRenderingContext::SetFont(const nsFont& aFont, nsIAtom* aLanguage,
                                   gfxUserFontSet *aUserFontSet)
 {
     PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::SetFont %p\n", this, &aFont));
 
     nsCOMPtr<nsIFontMetrics> newMetrics;
-    mDeviceContext->GetMetricsFor(aFont, aLangGroup, aUserFontSet,
+    mDeviceContext->GetMetricsFor(aFont, aLanguage, aUserFontSet,
+                                  *getter_AddRefs(newMetrics));
+    mFontMetrics = reinterpret_cast<nsIThebesFontMetrics*>(newMetrics.get());
+    return NS_OK;
+}
+
+NS_IMETHODIMP
+nsThebesRenderingContext::SetFont(const nsFont& aFont,
+                                  gfxUserFontSet *aUserFontSet)
+{
+    PR_LOG(gThebesGFXLog, PR_LOG_DEBUG, ("## %p nsTRC::SetFont %p\n", this, &aFont));
+
+    nsCOMPtr<nsIFontMetrics> newMetrics;
+    mDeviceContext->GetMetricsFor(aFont, nsnull, aUserFontSet,
                                   *getter_AddRefs(newMetrics));
     mFontMetrics = reinterpret_cast<nsIThebesFontMetrics*>(newMetrics.get());
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsThebesRenderingContext::SetFont(nsIFontMetrics *aFontMetrics)
 {
--- a/gfx/src/thebes/nsThebesRenderingContext.h
+++ b/gfx/src/thebes/nsThebesRenderingContext.h
@@ -138,17 +138,19 @@ public:
     NS_IMETHOD GetDeviceContext(nsIDeviceContext *& aDeviceContext);
     NS_IMETHOD PushState(void);
     NS_IMETHOD PopState(void);
     NS_IMETHOD SetClipRect(const nsRect& aRect, nsClipCombine aCombine);
     NS_IMETHOD SetLineStyle(nsLineStyle aLineStyle);
     NS_IMETHOD SetClipRegion(const nsIRegion& aRegion, nsClipCombine aCombine);
     NS_IMETHOD SetColor(nscolor aColor);
     NS_IMETHOD GetColor(nscolor &aColor) const;
-    NS_IMETHOD SetFont(const nsFont& aFont, nsIAtom* aLangGroup,
+    NS_IMETHOD SetFont(const nsFont& aFont, nsIAtom* aLanguage,
+                       gfxUserFontSet *aUserFontSet);
+    NS_IMETHOD SetFont(const nsFont& aFont,
                        gfxUserFontSet *aUserFontSet);
     NS_IMETHOD SetFont(nsIFontMetrics *aFontMetrics);
     NS_IMETHOD GetFontMetrics(nsIFontMetrics *&aFontMetrics);
     NS_IMETHOD Translate(nscoord aX, nscoord aY);
     NS_IMETHOD Scale(float aSx, float aSy);
     NS_IMETHOD GetCurrentTransform(nsTransform2D *&aTransform);
 
     NS_IMETHOD DrawLine(nscoord aX0, nscoord aY0, nscoord aX1, nscoord aY1);
--- a/gfx/thebes/public/gfxFont.h
+++ b/gfx/thebes/public/gfxFont.h
@@ -63,31 +63,33 @@ class gfxContext;
 class gfxTextRun;
 class nsIAtom;
 class gfxFont;
 class gfxFontFamily;
 class gfxFontGroup;
 class gfxUserFontSet;
 class gfxUserFontData;
 
+class nsILanguageAtomService;
+
 // We should eliminate these synonyms when it won't cause many merge conflicts.
 #define FONT_STYLE_NORMAL              NS_FONT_STYLE_NORMAL
 #define FONT_STYLE_ITALIC              NS_FONT_STYLE_ITALIC
 #define FONT_STYLE_OBLIQUE             NS_FONT_STYLE_OBLIQUE
 
 // We should eliminate these synonyms when it won't cause many merge conflicts.
 #define FONT_WEIGHT_NORMAL             NS_FONT_WEIGHT_NORMAL
 #define FONT_WEIGHT_BOLD               NS_FONT_WEIGHT_BOLD
 
 #define FONT_MAX_SIZE                  2000.0
 
 struct THEBES_API gfxFontStyle {
     gfxFontStyle();
     gfxFontStyle(PRUint8 aStyle, PRUint16 aWeight, PRInt16 aStretch,
-                 gfxFloat aSize, const nsACString& aLangGroup,
+                 gfxFloat aSize, const nsACString& aLanguage,
                  float aSizeAdjust, PRPackedBool aSystemFont,
                  PRPackedBool aFamilyNameQuirks,
                  PRPackedBool aPrinterFont);
     gfxFontStyle(const gfxFontStyle& aStyle);
 
     // The style of font (normal, italic, oblique)
     PRUint8 style : 7;
 
@@ -112,18 +114,18 @@ struct THEBES_API gfxFontStyle {
 
     // The stretch of the font (the sum of various NS_FONT_STRETCH_*
     // constants; see gfxFontConstants.h).
     PRInt16 stretch;
 
     // The logical size of the font, in pixels
     gfxFloat size;
 
-    // the language group
-    nsCString langGroup;
+    // the language (may be an internal langGroup code rather than an actual lang)
+    nsCString language;
 
     // The aspect-value (ie., the ratio actualsize:actualxheight) that any
     // actual physical font created from this font structure must have when
     // rendering or measuring a string. A value of 0 means no adjustment
     // needs to be done.
     float sizeAdjust;
 
     // Return the final adjusted font size for the given aspect ratio.
@@ -132,31 +134,31 @@ struct THEBES_API gfxFontStyle {
         NS_ASSERTION(sizeAdjust != 0.0, "Not meant to be called when sizeAdjust = 0");
         gfxFloat adjustedSize = PR_MAX(NS_round(size*(sizeAdjust/aspect)), 1.0);
         return PR_MIN(adjustedSize, FONT_MAX_SIZE);
     }
 
     PLDHashNumber Hash() const {
         return ((style + (systemFont << 7) + (familyNameQuirks << 8) +
             (weight << 9)) + PRUint32(size*1000) + PRUint32(sizeAdjust*1000)) ^
-            HashString(langGroup);
+            HashString(language);
     }
 
     void ComputeWeightAndOffset(PRInt8 *outBaseWeight,
                                 PRInt8 *outOffset) const;
 
     PRBool Equals(const gfxFontStyle& other) const {
         return (size == other.size) &&
             (style == other.style) &&
             (systemFont == other.systemFont) &&
             (printerFont == other.printerFont) &&
             (familyNameQuirks == other.familyNameQuirks) &&
             (weight == other.weight) &&
             (stretch == other.stretch) &&
-            (langGroup.Equals(other.langGroup)) &&
+            (language.Equals(other.language)) &&
             (sizeAdjust == other.sizeAdjust);
     }
 };
 
 class gfxFontEntry {
 public:
     THEBES_INLINE_DECL_REFCOUNTING(gfxFontEntry)
 
@@ -1712,16 +1714,18 @@ private:
     PRUint32          mFlags;
     PRUint32          mCharacterCount;
     PRUint32          mHashCode;
     PRUint64          mUserFontSetGeneration; // user font set generation when text run created
 };
 
 class THEBES_API gfxFontGroup : public gfxTextRunFactory {
 public:
+    static void Shutdown(); // platform must call this to release the languageAtomService
+
     gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet = nsnull);
 
     virtual ~gfxFontGroup();
 
     virtual gfxFont *GetFontAt(PRInt32 i) {
         // If it turns out to be hard for all clients that cache font
         // groups to call UpdateFontList at appropriate times, we could
         // instead consider just calling UpdateFontList from someplace
@@ -1782,20 +1786,20 @@ public:
                                     const Parameters *aParams, PRUint32 aFlags);
 
     /* helper function for splitting font families on commas and
      * calling a function for each family to fill the mFonts array
      */
     typedef PRBool (*FontCreationCallback) (const nsAString& aName,
                                             const nsACString& aGenericName,
                                             void *closure);
-    /*static*/ PRBool ForEachFont(const nsAString& aFamilies,
-                              const nsACString& aLangGroup,
-                              FontCreationCallback fc,
-                              void *closure);
+    PRBool ForEachFont(const nsAString& aFamilies,
+                       const nsACString& aLanguage,
+                       FontCreationCallback fc,
+                       void *closure);
     PRBool ForEachFont(FontCreationCallback fc, void *closure);
 
     /**
      * Check whether a given font (specified by its gfxFontEntry)
      * is already in the fontgroup's list of actual fonts
      */
     PRBool HasFont(const gfxFontEntry *aFontEntry);
 
@@ -1869,22 +1873,22 @@ protected:
     /* If aResolveGeneric is true, then CSS/Gecko generic family names are
      * replaced with preferred fonts.
      *
      * If aResolveFontName is true then fc() is called only for existing fonts
      * and with actual font names.  If false then fc() is called with each
      * family name in aFamilies (after resolving CSS/Gecko generic family names
      * if aResolveGeneric).
      */
-    /*static*/ PRBool ForEachFontInternal(const nsAString& aFamilies,
-                                      const nsACString& aLangGroup,
-                                      PRBool aResolveGeneric,
-                                      PRBool aResolveFontName,
-                                      FontCreationCallback fc,
-                                      void *closure);
+    PRBool ForEachFontInternal(const nsAString& aFamilies,
+                               const nsACString& aLanguage,
+                               PRBool aResolveGeneric,
+                               PRBool aResolveFontName,
+                               FontCreationCallback fc,
+                               void *closure);
 
     static PRBool FontResolverProc(const nsAString& aName, void *aClosure);
 
     static PRBool FindPlatformFont(const nsAString& aName,
                                    const nsACString& aGenericName,
                                    void *closure);
 
     inline gfxFont* WhichFontSupportsChar(nsTArray< nsRefPtr<gfxFont> >& aFontList, PRUint32 aCh) {
@@ -1892,10 +1896,11 @@ protected:
         for (PRUint32 i = 0; i < len; i++) {
             gfxFont* font = aFontList.ElementAt(i);
             if (font && font->HasCharacter(aCh))
                 return font;
         }
         return nsnull;
     }
 
+    static NS_HIDDEN_(nsILanguageAtomService*) gLangService;
 };
 #endif
--- a/gfx/thebes/public/gfxPangoFonts.h
+++ b/gfx/thebes/public/gfxPangoFonts.h
@@ -145,17 +145,17 @@ protected:
                                   PRUint32 aUTF8HeaderLength);
 #if defined(ENABLE_FAST_PATH_8BIT) || defined(ENABLE_FAST_PATH_ALWAYS)
     PRBool CanTakeFastPath(PRUint32 aFlags);
     nsresult CreateGlyphRunsFast(gfxTextRun *aTextRun,
                                  const gchar *aUTF8, PRUint32 aUTF8Length);
 #endif
 
     void GetFcFamilies(nsTArray<nsString> *aFcFamilyList,
-                       const nsACString& aLangGroup);
+                       const nsACString& aLanguage);
 
     // @param aLang [in] language to use for pref fonts and system font
     //        resolution, or NULL to guess a language from the gfxFontStyle.
     // @param aMatchPattern [out] if non-NULL, will return the pattern used.
     already_AddRefed<gfxFcPangoFontSet>
     MakeFontSet(PangoLanguage *aLang, gfxFloat aSizeAdjustFactor,
                 nsAutoRef<FcPattern> *aMatchPattern = NULL);
 
--- a/gfx/thebes/public/gfxPlatform.h
+++ b/gfx/thebes/public/gfxPlatform.h
@@ -227,17 +227,17 @@ public:
     /**
      * Whether to allow downloadable fonts via @font-face rules
      */
     virtual PRBool DownloadableFontsEnabled();
 
     // check whether format is supported on a platform or not (if unclear, returns true)
     virtual PRBool IsFontFormatSupported(nsIURI *aFontURI, PRUint32 aFormatFlags) { return PR_FALSE; }
 
-    void GetPrefFonts(const char *aLangGroup, nsString& array, PRBool aAppendUnicode = PR_TRUE);
+    void GetPrefFonts(const char *aLanguage, nsString& array, PRBool aAppendUnicode = PR_TRUE);
 
     // in some situations, need to make decisions about ambiguous characters, may need to look at multiple pref langs
     void GetLangPrefs(eFontPrefLang aPrefLangs[], PRUint32 &aLen, eFontPrefLang aCharLang, eFontPrefLang aPageLang);
     
     /**
      * Iterate over pref fonts given a list of lang groups.  For a single lang
      * group, multiple pref fonts are possible.  If error occurs, returns PR_FALSE,
      * PR_TRUE otherwise.  Callback returns PR_FALSE to abort process.
--- a/gfx/thebes/src/gfxFT2Fonts.cpp
+++ b/gfx/thebes/src/gfxFT2Fonts.cpp
@@ -331,19 +331,19 @@ gfxFT2FontGroup::gfxFT2FontGroup(const n
 #ifdef DEBUG_pavlov
     printf("Looking for %s\n", NS_ConvertUTF16toUTF8(families).get());
 #endif
     nsTArray<nsString> familyArray;
     ForEachFont(FontCallback, &familyArray);
 
     if (familyArray.Length() == 0) {
         nsAutoString prefFamilies;
-        gfxToolkitPlatform::GetPlatform()->GetPrefFonts(aStyle->langGroup.get(), prefFamilies, nsnull);
+        gfxToolkitPlatform::GetPlatform()->GetPrefFonts(aStyle->language.get(), prefFamilies, nsnull);
         if (!prefFamilies.IsEmpty()) {
-            ForEachFont(prefFamilies, aStyle->langGroup, FontCallback, &familyArray);
+            ForEachFont(prefFamilies, aStyle->language, FontCallback, &familyArray);
         }
     }
     if (familyArray.Length() == 0) {
 #if defined(MOZ_WIDGET_QT) /* FIXME DFB */
         printf("failde to find a font. sadface\n");
         // We want to get rid of this entirely at some point, but first we need real lists of fonts.
         QFont defaultFont;
         QFontInfo fi (defaultFont);
@@ -639,19 +639,19 @@ gfxFT2FontGroup::WhichFontSupportsChar(c
 already_AddRefed<gfxFont>
 gfxFT2FontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
 {
     if (aCh > 0xFFFF)
         return nsnull;
 
     nsRefPtr<gfxFT2Font> selectedFont;
 
-    // check out the style's language group
+    // check out the style's language
     nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
-    GetPrefFonts(mStyle.langGroup.get(), fonts);
+    GetPrefFonts(mStyle.language.get(), fonts);
     selectedFont = WhichFontSupportsChar(fonts, aCh);
 
     // otherwise search prefs
     if (!selectedFont) {
         PRUint32 unicodeRange = FindCharUnicodeRange(aCh);
 
         /* special case CJK */
         if (unicodeRange == kRangeSetCJK) {
--- a/gfx/thebes/src/gfxFont.cpp
+++ b/gfx/thebes/src/gfxFont.cpp
@@ -37,16 +37,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIPrefService.h"
 #include "nsServiceManagerUtils.h"
 #include "nsReadableUtils.h"
 #include "nsExpirationTracker.h"
+#include "nsILanguageAtomService.h"
 
 #include "gfxFont.h"
 #include "gfxPlatform.h"
 
 #include "prtypes.h"
 #include "gfxTypes.h"
 #include "gfxContext.h"
 #include "gfxFontMissingGlyphs.h"
@@ -1412,17 +1413,17 @@ gfxGlyphExtents::SetTightGlyphExtents(PR
 }
 
 gfxFontGroup::gfxFontGroup(const nsAString& aFamilies, const gfxFontStyle *aStyle, gfxUserFontSet *aUserFontSet)
     : mFamilies(aFamilies), mStyle(*aStyle), mUnderlineOffset(UNDERLINE_OFFSET_NOT_SET)
 {
     mUserFontSet = nsnull;
     SetUserFontSet(aUserFontSet);
 
-    mPageLang = gfxPlatform::GetFontPrefLangFor(mStyle.langGroup.get());
+    mPageLang = gfxPlatform::GetFontPrefLangFor(mStyle.language.get());
     BuildFontList();
 }
 
 void
 gfxFontGroup::BuildFontList()
 {
 // "#if" to be removed once all platforms are moved to gfxPlatformFontList interface
 // and subclasses of gfxFontGroup eliminated
@@ -1525,27 +1526,27 @@ gfxFontGroup::IsInvalidChar(PRUnichar ch
     return ch == 0x0B || ch == '\t' || ch == '\r' || ch == '\n' || ch == '\f' ||
         (ch >= 0x1c && ch <= 0x1f);
 }
 
 PRBool
 gfxFontGroup::ForEachFont(FontCreationCallback fc,
                           void *closure)
 {
-    return ForEachFontInternal(mFamilies, mStyle.langGroup,
+    return ForEachFontInternal(mFamilies, mStyle.language,
                                PR_TRUE, PR_TRUE, fc, closure);
 }
 
 PRBool
 gfxFontGroup::ForEachFont(const nsAString& aFamilies,
-                          const nsACString& aLangGroup,
+                          const nsACString& aLanguage,
                           FontCreationCallback fc,
                           void *closure)
 {
-    return ForEachFontInternal(aFamilies, aLangGroup,
+    return ForEachFontInternal(aFamilies, aLanguage,
                                PR_FALSE, PR_TRUE, fc, closure);
 }
 
 struct ResolveData {
     ResolveData(gfxFontGroup::FontCreationCallback aCallback,
                 nsACString& aGenericFamily,
                 void *aClosure) :
         mCallback(aCallback),
@@ -1554,39 +1555,53 @@ struct ResolveData {
     }
     gfxFontGroup::FontCreationCallback mCallback;
     nsCString mGenericFamily;
     void *mClosure;
 };
 
 PRBool
 gfxFontGroup::ForEachFontInternal(const nsAString& aFamilies,
-                                  const nsACString& aLangGroup,
+                                  const nsACString& aLanguage,
                                   PRBool aResolveGeneric,
                                   PRBool aResolveFontName,
                                   FontCreationCallback fc,
                                   void *closure)
 {
     const PRUnichar kSingleQuote  = PRUnichar('\'');
     const PRUnichar kDoubleQuote  = PRUnichar('\"');
     const PRUnichar kComma        = PRUnichar(',');
 
+    nsCAutoString langGroup;
+    if (!gLangService) {
+        CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID, &gLangService);
+    }
+    if (gLangService) {
+        nsresult rv;
+        // temp, until we pass aLanguage as an Atom
+        nsCOMPtr<nsIAtom> lang = do_GetAtom(mStyle.language);
+        nsIAtom *group = gLangService->GetLanguageGroup(lang, &rv);
+        if (NS_SUCCEEDED(rv) && group) {
+            group->ToUTF8String(langGroup);
+        }
+    }
+    if (langGroup.IsEmpty()) {
+        langGroup.Assign("x-unicode"); // XXX or should use "x-user-def"?
+    }
+
     nsCOMPtr<nsIPrefBranch> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID);
 
     nsPromiseFlatString families(aFamilies);
     const PRUnichar *p, *p_end;
     families.BeginReading(p);
     families.EndReading(p_end);
     nsAutoString family;
     nsCAutoString lcFamily;
     nsAutoString genericFamily;
     nsXPIDLCString value;
-    nsCAutoString lang(aLangGroup);
-    if (lang.IsEmpty())
-        lang.Assign("x-unicode"); // XXX or should use "x-user-def"?
 
     while (p < p_end) {
         while (nsCRT::IsAsciiSpace(*p))
             if (++p == p_end)
                 return PR_TRUE;
 
         PRBool generic;
         if (*p == kSingleQuote || *p == kDoubleQuote) {
@@ -1626,33 +1641,34 @@ gfxFontGroup::ForEachFontInternal(const 
             {
                 generic = PR_TRUE;
 
                 ToLowerCase(NS_LossyConvertUTF16toASCII(family), lcFamily);
 
                 nsCAutoString prefName("font.name.");
                 prefName.Append(lcFamily);
                 prefName.AppendLiteral(".");
-                prefName.Append(lang);
+                prefName.Append(langGroup);
 
                 // prefs file always uses (must use) UTF-8 so that we can use
                 // |GetCharPref| and treat the result as a UTF-8 string.
                 nsresult rv = prefs->GetCharPref(prefName.get(), getter_Copies(value));
                 if (NS_SUCCEEDED(rv)) {
                     CopyASCIItoUTF16(lcFamily, genericFamily);
                     CopyUTF8toUTF16(value, family);
                 }
             } else {
                 generic = PR_FALSE;
                 genericFamily.SetIsVoid(PR_TRUE);
             }
         }
 
         if (generic) {
-            ForEachFontInternal(family, lang, PR_FALSE, aResolveFontName, fc, closure);
+            ForEachFontInternal(family, langGroup, PR_FALSE,
+                                aResolveFontName, fc, closure);
         } else if (!family.IsEmpty()) {
             NS_LossyConvertUTF16toASCII gf(genericFamily);
             if (aResolveFontName) {
                 ResolveData data(fc, gf, closure);
                 PRBool aborted = PR_FALSE, needsBold;
                 nsresult rv;
 
                 if (mUserFontSet && mUserFontSet->FindFontEntry(family, mStyle, needsBold)) {
@@ -1672,21 +1688,21 @@ gfxFontGroup::ForEachFontInternal(const 
                     return PR_FALSE;
             }
         }
 
         if (generic && aResolveGeneric) {
             nsCAutoString prefName("font.name-list.");
             prefName.Append(lcFamily);
             prefName.AppendLiteral(".");
-            prefName.Append(aLangGroup);
+            prefName.Append(langGroup);
             nsresult rv = prefs->GetCharPref(prefName.get(), getter_Copies(value));
             if (NS_SUCCEEDED(rv)) {
                 ForEachFontInternal(NS_ConvertUTF8toUTF16(value),
-                                    lang, PR_FALSE, aResolveFontName,
+                                    langGroup, PR_FALSE, aResolveFontName,
                                     fc, closure);
             }
         }
 
         ++p; // may advance past p_end
     }
 
     return PR_TRUE;
@@ -2132,58 +2148,67 @@ gfxFontGroup::WhichSystemFontSupportsCha
     if (fe) {
         nsRefPtr<gfxFont> font = fe->FindOrMakeFont(&mStyle, PR_FALSE); // ignore bolder considerations in system fallback case...
         return font.forget();
     }
 
     return nsnull;
 }
 
+/*static*/ void
+gfxFontGroup::Shutdown()
+{
+    NS_IF_RELEASE(gLangService);
+}
+
+nsILanguageAtomService* gfxFontGroup::gLangService = nsnull;
+
+
 #define DEFAULT_PIXEL_FONT_SIZE 16.0f
 
 gfxFontStyle::gfxFontStyle() :
     style(FONT_STYLE_NORMAL), systemFont(PR_TRUE), printerFont(PR_FALSE), 
     familyNameQuirks(PR_FALSE), weight(FONT_WEIGHT_NORMAL),
     stretch(NS_FONT_STRETCH_NORMAL), size(DEFAULT_PIXEL_FONT_SIZE),
-    langGroup(NS_LITERAL_CSTRING("x-western")), sizeAdjust(0.0f)
+    language(NS_LITERAL_CSTRING("x-western")), sizeAdjust(0.0f)
 {
 }
 
 gfxFontStyle::gfxFontStyle(PRUint8 aStyle, PRUint16 aWeight, PRInt16 aStretch,
-                           gfxFloat aSize, const nsACString& aLangGroup,
+                           gfxFloat aSize, const nsACString& aLanguage,
                            float aSizeAdjust, PRPackedBool aSystemFont,
                            PRPackedBool aFamilyNameQuirks,
                            PRPackedBool aPrinterFont):
     style(aStyle), systemFont(aSystemFont), printerFont(aPrinterFont),
     familyNameQuirks(aFamilyNameQuirks), weight(aWeight), stretch(aStretch),
-    size(aSize), langGroup(aLangGroup), sizeAdjust(aSizeAdjust)
+    size(aSize), language(aLanguage), sizeAdjust(aSizeAdjust)
 {
     if (weight > 900)
         weight = 900;
     if (weight < 100)
         weight = 100;
 
     if (size >= FONT_MAX_SIZE) {
         size = FONT_MAX_SIZE;
         sizeAdjust = 0.0;
     } else if (size < 0.0) {
         NS_WARNING("negative font size");
         size = 0.0;
     }
 
-    if (langGroup.IsEmpty()) {
-        NS_WARNING("empty langgroup");
-        langGroup.Assign("x-western");
+    if (language.IsEmpty()) {
+        NS_WARNING("empty language");
+        language.Assign("x-western");
     }
 }
 
 gfxFontStyle::gfxFontStyle(const gfxFontStyle& aStyle) :
     style(aStyle.style), systemFont(aStyle.systemFont), printerFont(aStyle.printerFont),
     familyNameQuirks(aStyle.familyNameQuirks), weight(aStyle.weight),
-    stretch(aStyle.stretch), size(aStyle.size), langGroup(aStyle.langGroup),
+    stretch(aStyle.stretch), size(aStyle.size), language(aStyle.language),
     sizeAdjust(aStyle.sizeAdjust)
 {
 }
 
 void
 gfxFontStyle::ComputeWeightAndOffset(PRInt8 *outBaseWeight, PRInt8 *outOffset) const
 {
     PRInt8 baseWeight = (weight + 50) / 100;
@@ -3493,13 +3518,13 @@ gfxTextRun::Dump(FILE* aOutput) {
         if (i > 0) {
             fputc(',', aOutput);
         }
         gfxFont* font = mGlyphRuns[i].mFont;
         const gfxFontStyle* style = font->GetStyle();
         NS_ConvertUTF16toUTF8 fontName(font->GetName());
         fprintf(aOutput, "%d: %s %f/%d/%d/%s", mGlyphRuns[i].mCharacterOffset,
                 fontName.get(), style->size,
-                style->weight, style->style, style->langGroup.get());
+                style->weight, style->style, style->language.get());
     }
     fputc(']', aOutput);
 }
 #endif
--- a/gfx/thebes/src/gfxPangoFonts.cpp
+++ b/gfx/thebes/src/gfxPangoFonts.cpp
@@ -100,17 +100,16 @@ static PangoLanguage *GuessPangoLanguage
 
 static cairo_scaled_font_t *CreateScaledFont(FcPattern *aPattern);
 
 static PangoFontMap *gPangoFontMap;
 static PangoFontMap *GetPangoFontMap();
 static PRBool gUseFontMapProperty;
 
 static FT_Library gFTLibrary;
-static nsILanguageAtomService* gLangService;
 
 NS_SPECIALIZE_TEMPLATE
 class nsAutoRefTraits<PangoFont> : public gfxGObjectRefTraits<PangoFont> { };
 
 NS_SPECIALIZE_TEMPLATE
 class nsAutoRefTraits<PangoCoverage>
     : public nsPointerRefTraits<PangoCoverage> {
 public:
@@ -1883,17 +1882,17 @@ FamilyCallback (const nsAString& fontNam
 
     return PR_TRUE;
 }
 
 gfxPangoFontGroup::gfxPangoFontGroup (const nsAString& families,
                                       const gfxFontStyle *aStyle,
                                       gfxUserFontSet *aUserFontSet)
     : gfxFontGroup(families, aStyle, aUserFontSet),
-      mPangoLanguage(GuessPangoLanguage(aStyle->langGroup))
+      mPangoLanguage(GuessPangoLanguage(aStyle->language))
 {
     mFonts.AppendElements(1);
 }
 
 gfxPangoFontGroup::~gfxPangoFontGroup()
 {
 }
 
@@ -1901,22 +1900,22 @@ gfxFontGroup *
 gfxPangoFontGroup::Copy(const gfxFontStyle *aStyle)
 {
     return new gfxPangoFontGroup(mFamilies, aStyle, mUserFontSet);
 }
 
 // An array of family names suitable for fontconfig
 void
 gfxPangoFontGroup::GetFcFamilies(nsTArray<nsString> *aFcFamilyList,
-                                 const nsACString& aLangGroup)
+                                 const nsACString& aLanguage)
 {
     FamilyCallbackData data(aFcFamilyList, mUserFontSet);
     // Leave non-existing fonts in the list so that fontconfig can get the
     // best match.
-    ForEachFontInternal(mFamilies, aLangGroup, PR_TRUE, PR_FALSE,
+    ForEachFontInternal(mFamilies, aLanguage, PR_TRUE, PR_FALSE,
                         FamilyCallback, &data);
 }
 
 PangoFont *
 gfxPangoFontGroup::GetBasePangoFont()
 {
     return GetBaseFontSet()->GetFontAt(0);
 }
@@ -1975,17 +1974,17 @@ gfxPangoFontGroup::MakeFontSet(PangoLang
             if (atom) {
                 atom->GetUTF8String(&langGroup);
             }
         }
     }
 
     nsAutoTArray<nsString, 20> fcFamilyList;
     GetFcFamilies(&fcFamilyList,
-                  langGroup ? nsDependentCString(langGroup) : mStyle.langGroup);
+                  langGroup ? nsDependentCString(langGroup) : mStyle.language);
 
     // To consider: A fontset cache here could be helpful.
 
     // Get a pattern suitable for matching.
     nsAutoRef<FcPattern> pattern
         (gfxFontconfigUtils::NewPattern(fcFamilyList, mStyle, lang));
 
     PrepareSortPattern(pattern, mStyle.size, aSizeAdjustFactor, mStyle.printerFont);
@@ -2057,18 +2056,16 @@ gfxPangoFontGroup::Shutdown()
         }
         g_object_unref(gPangoFontMap);
         gPangoFontMap = NULL;
     }
 
     // Resetting gFTLibrary in case this is wanted again after a
     // cairo_debug_reset_static_data.
     gFTLibrary = NULL;
-
-    NS_IF_RELEASE(gLangService);
 }
 
 /* static */ gfxFontEntry *
 gfxPangoFontGroup::NewFontEntry(const gfxProxyFontEntry &aProxyEntry,
                                 const nsAString& aFullname)
 {
     gfxFontconfigUtils *utils = gfxFontconfigUtils::GetFontconfigUtils();
     if (!utils)
@@ -2206,20 +2203,20 @@ gfxFcFont::GetOrMakeFont(FcPattern *aPat
         // Shouldn't actually need to take too much care about the correct
         // name or style, as size is the only thing expected to be important.
         PRUint8 style = gfxFontconfigUtils::GetThebesStyle(aPattern);
         PRUint16 weight = gfxFontconfigUtils::GetThebesWeight(aPattern);
 
         // The LangSet in the FcPattern does not have an order so there is no
         // one particular language to choose and converting the set to a
         // string through FcNameUnparse() is more trouble than it's worth.
-        NS_NAMED_LITERAL_CSTRING(langGroup, "x-unicode");
+        NS_NAMED_LITERAL_CSTRING(language, "en"); // TODO: get the correct language?
         // FIXME: Pass a real stretch based on aPattern!
         gfxFontStyle fontStyle(style, weight, NS_FONT_STRETCH_NORMAL,
-                               size, langGroup, 0.0,
+                               size, language, 0.0,
                                PR_TRUE, PR_FALSE, PR_FALSE);
 
         nsRefPtr<gfxFontEntry> fe;
         FcChar8 *fc_file;
         if (FcPatternGetString(aPattern,
                                FC_FILE, 0, &fc_file) == FcResultMatch) {
             int index;
             if (FcPatternGetInteger(aPattern,
--- a/gfx/thebes/src/gfxPlatform.cpp
+++ b/gfx/thebes/src/gfxPlatform.cpp
@@ -237,16 +237,17 @@ gfxPlatform::Init()
 void
 gfxPlatform::Shutdown()
 {
     // These may be called before the corresponding subsystems have actually
     // started up. That's OK, they can handle it.
     gfxTextRunCache::Shutdown();
     gfxTextRunWordCache::Shutdown();
     gfxFontCache::Shutdown();
+    gfxFontGroup::Shutdown();
 #if defined(XP_MACOSX) || defined(XP_WIN) // temporary, until this is implemented on others
     gfxPlatformFontList::Shutdown();
 #endif
 
     // Free the various non-null transforms and loaded profiles
     ShutdownCMS();
 
     /* Unregister our CMS Override callback. */
@@ -392,21 +393,21 @@ AppendGenericFontFromPref(nsString& aFon
     if (NS_SUCCEEDED(rv) && !nameListValue.Equals(nameValue)) {
         if (!aFonts.IsEmpty())
             aFonts.AppendLiteral(", ");
         aFonts.Append(NS_ConvertUTF8toUTF16(nameListValue));
     }
 }
 
 void
-gfxPlatform::GetPrefFonts(const char *aLangGroup, nsString& aFonts, PRBool aAppendUnicode)
+gfxPlatform::GetPrefFonts(const char *aLanguage, nsString& aFonts, PRBool aAppendUnicode)
 {
     aFonts.Truncate();
 
-    AppendGenericFontFromPref(aFonts, aLangGroup, nsnull);
+    AppendGenericFontFromPref(aFonts, aLanguage, nsnull);
     if (aAppendUnicode)
         AppendGenericFontFromPref(aFonts, "x-unicode", nsnull);
 }
 
 PRBool gfxPlatform::ForEachPrefFont(eFontPrefLang aLangArray[], PRUint32 aLangArrayLen, PrefFontCallback aCallback,
                                     void *aClosure)
 {
     nsresult rv;
--- a/gfx/thebes/src/gfxPlatformFontList.cpp
+++ b/gfx/thebes/src/gfxPlatformFontList.cpp
@@ -279,17 +279,17 @@ gfxPlatformFontList::HashEnumFuncForFami
                                              void *aUserArg)
 {
     FontListData *data = static_cast<FontListData*>(aUserArg);
 
     // use the first variation for now.  This data should be the same
     // for all the variations and should probably be moved up to
     // the Family
     gfxFontStyle style;
-    style.langGroup = data->mLangGroup;
+    style.language = data->mLangGroup;
     PRBool needsBold;
     nsRefPtr<gfxFontEntry> aFontEntry = aFamilyEntry->FindFontForStyle(style, needsBold);
     NS_ASSERTION(aFontEntry, "couldn't find any font entry in family");
     if (!aFontEntry)
         return PL_DHASH_NEXT;
 
     /* skip symbol fonts */
     if (aFontEntry->IsSymbolFont())
@@ -301,17 +301,17 @@ gfxPlatformFontList::HashEnumFuncForFami
         aFamilyEntry->LocalizedName(localizedFamilyName);
         data->mListOfFonts.AppendElement(localizedFamilyName);
     }
 
     return PL_DHASH_NEXT;
 }
 
 void
-gfxPlatformFontList::GetFontList (const nsACString& aLangGroup,
+gfxPlatformFontList::GetFontList(const nsACString& aLangGroup,
                                  const nsACString& aGenericFamily,
                                  nsTArray<nsString>& aListOfFonts)
 {
     FontListData data(aLangGroup, aGenericFamily, aListOfFonts);
 
     mFontFamilies.Enumerate(gfxPlatformFontList::HashEnumFuncForFamilies, &data);
 
     aListOfFonts.Sort();
--- a/gfx/thebes/src/gfxWindowsFonts.cpp
+++ b/gfx/thebes/src/gfxWindowsFonts.cpp
@@ -1828,17 +1828,17 @@ void gfxWindowsFontGroup::GetCJKPrefFont
 already_AddRefed<gfxFont> 
 gfxWindowsFontGroup::WhichPrefFontSupportsChar(PRUint32 aCh)
 {
     nsRefPtr<gfxWindowsFont> selectedFont;
 
     // check out the style's language group
     if (!selectedFont) {
         nsAutoTArray<nsRefPtr<gfxFontEntry>, 5> fonts;
-        this->GetPrefFonts(mStyle.langGroup.get(), fonts);
+        this->GetPrefFonts(mStyle.language.get(), fonts);
         selectedFont = WhichFontSupportsChar(fonts, aCh);
     }
 
     // otherwise search prefs
     if (!selectedFont) {
         /* first check with the script properties to see what they think */
         if (mItemLangGroup) {
             PR_LOG(gFontLog, PR_LOG_DEBUG, (" - Trying to find fonts for: %s ", mItemLangGroup));
--- a/gfx/thebes/test/gfxFontSelectionTests.h
+++ b/gfx/thebes/test/gfxFontSelectionTests.h
@@ -104,25 +104,25 @@ SetupTests()
 {
     TestEntry *t;
 
     /* some common styles */
     gfxFontStyle style_western_normal_16 (FONT_STYLE_NORMAL,
                                           NS_FONT_STRETCH_NORMAL,
                                           400,
                                           16.0,
-                                          nsDependentCString("x-western"),
+                                          nsDependentCString("en"),
                                           0.0,
                                           PR_FALSE, PR_FALSE, PR_FALSE);
 
     gfxFontStyle style_western_bold_16 (FONT_STYLE_NORMAL,
                                         NS_FONT_STRETCH_NORMAL,
                                         700,
                                         16.0,
-                                        nsDependentCString("x-western"),
+                                        nsDependentCString("en"),
                                         0.0,
                                         PR_FALSE, PR_FALSE, PR_FALSE);
 
     /* Test 0 */
     t = AddTest ("sans-serif",
                  style_western_normal_16,
                  S_ASCII,
                  "ABCD");
--- a/gfx/thebes/test/gfxTextRunPerfTest.cpp
+++ b/gfx/thebes/test/gfxTextRunPerfTest.cpp
@@ -88,17 +88,17 @@ const char* lastFamilies = nsnull;
 
 void
 RunTest (TestEntry *test, gfxContext *ctx) {
     if (!lastFamilies || strcmp(lastFamilies, test->mFamilies)) {
         gfxFontStyle style_western_normal_16 (FONT_STYLE_NORMAL,
                                               NS_FONT_STRETCH_NORMAL,
                                               400,
                                               16.0,
-                                              nsDependentCString("x-western"),
+                                              nsDependentCString("en"),
                                               0.0,
                                               PR_FALSE, PR_FALSE, PR_FALSE);
 
         fontGroup = gfxPlatform::GetPlatform()->CreateFontGroup(NS_ConvertUTF8toUTF16(test->mFamilies), &style_western_normal_16, nsnull);
     }
 
     nsAutoPtr<gfxTextRun> textRun;
     PRUint32 i;
--- a/gfx/thebes/test/gfxWordCacheTest.cpp
+++ b/gfx/thebes/test/gfxWordCacheTest.cpp
@@ -154,17 +154,17 @@ main (int argc, char **argv) {
    gTextRuns = new FrameTextRunCache();
 
    nsRefPtr<gfxContext> ctx = MakeContext();
    {
        gfxFontStyle style (FONT_STYLE_NORMAL,
                            NS_FONT_STRETCH_NORMAL,
                            139,
                            10.0,
-                           nsDependentCString("x-western"),
+                           nsDependentCString("en"),
                            0.0,
                            PR_FALSE, PR_FALSE, PR_FALSE);
 
        nsRefPtr<gfxFontGroup> fontGroup =
            gfxPlatform::GetPlatform()->CreateFontGroup(NS_LITERAL_STRING("Geneva, MS Sans Serif, Helvetica,serif"), &style, nsnull);
 
        gfxTextRunFactory::Parameters params = {
            ctx, nsnull, nsnull, nsnull, 0, 60
--- a/intl/locale/public/nsILanguageAtomService.h
+++ b/intl/locale/public/nsILanguageAtomService.h
@@ -18,16 +18,17 @@
  * The Initial Developer of the Original Code is
  * Netscape Communications Corp.
  * Portions created by the Initial Developer are Copyright (C) 2000
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
  *   Erik van der Poel
  *   Brian Ryner <bryner@brianryner.com>
+ *   Jonathan Kew <jfkthame@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of the GNU General Public License Version 2 or later (the "GPL"),
  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  * in which case the provisions of the GPL or the LGPL are applicable instead
  * of those above. If you wish to allow use of your version of this file only
  * under the terms of either the GPL or the LGPL, and not to allow others to
  * use your version of this file under the terms of the MPL, indicate your
@@ -37,40 +38,43 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsILanguageAtomService_h_
 #define nsILanguageAtomService_h_
 
 /*
- * The nsILanguageAtomService provides a mapping from languages or
- * character sets to language groups.
+ * The nsILanguageAtomService provides a mapping from languages or charsets
+ * to language groups, and access to the system locale language.
  */
 
 #include "nsISupports.h"
 #include "nsCOMPtr.h"
 #include "nsIAtom.h"
 
 #define NS_ILANGUAGEATOMSERVICE_IID \
-  {0x24b45737, 0x9e94, 0x4e40, \
-    { 0x9d, 0x59, 0x29, 0xcd, 0x62, 0x96, 0x3a, 0xdd }}
+  {0xE8ABCA7C, 0x3909, 0x4DBC, \
+    { 0x9D, 0x03, 0xD3, 0xB5, 0xBE, 0xE4, 0xFD, 0x3F }}
 
 #define NS_LANGUAGEATOMSERVICE_CONTRACTID \
   "@mozilla.org/intl/nslanguageatomservice;1"
 
 class nsILanguageAtomService : public nsISupports
 {
  public: 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ILANGUAGEATOMSERVICE_IID)
 
   virtual nsIAtom* LookupLanguage(const nsAString &aLanguage,
                                   nsresult *aError = nsnull) = 0;
   virtual already_AddRefed<nsIAtom>
   LookupCharSet(const char *aCharSet, nsresult *aError = nsnull) = 0;
 
-  virtual nsIAtom* GetLocaleLanguageGroup(nsresult *aError = nsnull) = 0;
+  virtual nsIAtom* GetLocaleLanguage(nsresult *aError = nsnull) = 0;
+
+  virtual nsIAtom* GetLanguageGroup(nsIAtom *aLanguage,
+                                    nsresult *aError = nsnull) = 0;
 };
 
 NS_DEFINE_STATIC_IID_ACCESSOR(nsILanguageAtomService,
                               NS_ILANGUAGEATOMSERVICE_IID)
 
 #endif
--- a/intl/locale/src/nsLanguageAtomService.cpp
+++ b/intl/locale/src/nsLanguageAtomService.cpp
@@ -37,95 +37,49 @@
 
 #include "nsIComponentManager.h"
 #include "nsLanguageAtomService.h"
 #include "nsICharsetConverterManager.h"
 #include "nsILocaleService.h"
 #include "nsXPIDLString.h"
 #include "nsUnicharUtils.h"
 #include "nsIServiceManager.h"
+#include "nsIAtom.h"
 
 NS_IMPL_ISUPPORTS1(nsLanguageAtomService, nsILanguageAtomService)
 
 nsLanguageAtomService::nsLanguageAtomService()
 {
-  mLangs.Init();
+  mLangToGroup.Init();
 }
 
 nsresult
 nsLanguageAtomService::InitLangGroupTable()
 {
   if (mLangGroups) return NS_OK;
   nsresult rv;
   
   nsCOMPtr<nsIStringBundleService> bundleService =
     do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
   if (NS_FAILED(rv)) return rv;
 
-
   rv = bundleService->CreateBundle("resource://gre/res/langGroups.properties",
                                    getter_AddRefs(mLangGroups));
   return rv;
 }
 
 nsIAtom*
 nsLanguageAtomService::LookupLanguage(const nsAString &aLanguage,
                                       nsresult *aError)
 {
-  nsresult res = NS_OK;
-
   nsAutoString lowered(aLanguage);
   ToLowerCase(lowered);
 
-  nsIAtom *lang = mLangs.GetWeak(lowered);
-
-  if (!lang) {
-    nsXPIDLString langGroupStr;
-
-    if (lowered.EqualsLiteral("en-us")) {
-      langGroupStr.AssignLiteral("x-western");
-    } else if (lowered.EqualsLiteral("de-de")) {
-      langGroupStr.AssignLiteral("x-western");
-    } else if (lowered.EqualsLiteral("ja-jp")) {
-      langGroupStr.AssignLiteral("ja");
-    } else {
-      if (!mLangGroups) {
-        if (NS_FAILED(InitLangGroupTable())) {
-          if (aError)
-            *aError = NS_ERROR_FAILURE;
-
-          return nsnull;
-        }
-      }
-      res = mLangGroups->GetStringFromName(lowered.get(), getter_Copies(langGroupStr));
-      if (NS_FAILED(res)) {
-        PRInt32 hyphen = lowered.FindChar('-');
-        if (hyphen >= 0) {
-          nsAutoString truncated(lowered);
-          truncated.Truncate(hyphen);
-          res = mLangGroups->GetStringFromName(truncated.get(), getter_Copies(langGroupStr));
-          if (NS_FAILED(res)) {
-            langGroupStr.AssignLiteral("x-unicode");
-          }
-        } else {
-          langGroupStr.AssignLiteral("x-unicode");
-        }
-      }
-    }
-    nsCOMPtr<nsIAtom> langGroup = do_GetAtom(langGroupStr);
-
-    // The hashtable will keep an owning reference to the atom
-    mLangs.Put(lowered, langGroup);
-    lang = langGroup;
-  }
-
-  if (aError)
-    *aError = res;
-
-  return lang;
+  nsCOMPtr<nsIAtom> lang = do_GetAtom(lowered);
+  return GetLanguageGroup(lang, aError);
 }
 
 already_AddRefed<nsIAtom>
 nsLanguageAtomService::LookupCharSet(const char *aCharSet, nsresult *aError)
 {
   if (!mCharSets) {
     mCharSets = do_GetService(NS_CHARSETCONVERTERMANAGER_CONTRACTID);
     if (!mCharSets) {
@@ -151,22 +105,22 @@ nsLanguageAtomService::LookupCharSet(con
 
   if (aError)
     *aError = NS_OK;
 
   return raw;
 }
 
 nsIAtom*
-nsLanguageAtomService::GetLocaleLanguageGroup(nsresult *aError)
+nsLanguageAtomService::GetLocaleLanguage(nsresult *aError)
 {
   nsresult res = NS_OK;
 
   do {
-    if (!mLocaleLangGroup) {
+    if (!mLocaleLanguage) {
       nsCOMPtr<nsILocaleService> localeService;
       localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID);
       if (!localeService) {
         res = NS_ERROR_FAILURE;
         break;
       }
 
       nsCOMPtr<nsILocale> locale;
@@ -176,17 +130,72 @@ nsLanguageAtomService::GetLocaleLanguage
 
       nsAutoString category;
       category.AssignWithConversion(NSILOCALE_MESSAGE);
       nsAutoString loc;
       res = locale->GetCategory(category, loc);
       if (NS_FAILED(res))
         break;
 
-      mLocaleLangGroup = LookupLanguage(loc, &res);
+      ToLowerCase(loc); // use lowercase for all language atoms
+      mLocaleLanguage = do_GetAtom(loc);
     }
   } while (0);
 
   if (aError)
     *aError = res;
 
-  return mLocaleLangGroup;
+  return mLocaleLanguage;
 }
+
+nsIAtom*
+nsLanguageAtomService::GetLanguageGroup(nsIAtom *aLanguage,
+                                        nsresult *aError)
+{
+  nsIAtom *retVal;
+  nsresult res = NS_OK;
+
+  retVal = mLangToGroup.GetWeak(aLanguage);
+
+  if (!retVal) {
+    if (!mLangGroups) {
+      if (NS_FAILED(InitLangGroupTable())) {
+        if (aError) {
+          *aError = NS_ERROR_FAILURE;
+        }
+        return nsnull;
+      }
+    }
+
+    nsString langStr;
+    aLanguage->ToString(langStr);
+
+    nsXPIDLString langGroupStr;
+    res = mLangGroups->GetStringFromName(langStr.get(),
+                                         getter_Copies(langGroupStr));
+    if (NS_FAILED(res)) {
+      PRInt32 hyphen = langStr.FindChar('-');
+      if (hyphen >= 0) {
+        nsAutoString truncated(langStr);
+        truncated.Truncate(hyphen);
+        res = mLangGroups->GetStringFromName(truncated.get(),
+                                             getter_Copies(langGroupStr));
+        if (NS_FAILED(res)) {
+          langGroupStr.AssignLiteral("x-unicode");
+        }
+      } else {
+        langGroupStr.AssignLiteral("x-unicode");
+      }
+    }
+
+    nsCOMPtr<nsIAtom> langGroup = do_GetAtom(langGroupStr);
+
+    // The hashtable will keep an owning reference to the atom
+    mLangToGroup.Put(aLanguage, langGroup);
+    retVal = langGroup.get();
+  }
+
+  if (aError) {
+    *aError = res;
+  }
+
+  return retVal;
+}
--- a/intl/locale/src/nsLanguageAtomService.h
+++ b/intl/locale/src/nsLanguageAtomService.h
@@ -39,37 +39,40 @@
 #include "nsICharsetConverterManager.h"
 #include "nsILanguageAtomService.h"
 #include "nsIStringBundle.h"
 #include "nsCRT.h"
 #include "nsInterfaceHashtable.h"
 #include "nsIAtom.h"
 
 #define NS_LANGUAGEATOMSERVICE_CID \
-  {0xa6cf9120, 0x15b3, 0x11d2, {0x93, 0x2e, 0x00, 0x80, 0x5f, 0x8a, 0xdd, 0x32}}
+  {0xB7C65853, 0x2996, 0x435E, {0x96, 0x54, 0xDC, 0xC1, 0x78, 0xAA, 0xB4, 0x8C}}
 
 class nsLanguageAtomService : public nsILanguageAtomService
 {
 public:
   NS_DECL_ISUPPORTS
 
   // nsILanguageAtomService
   virtual NS_HIDDEN_(nsIAtom*)
     LookupLanguage(const nsAString &aLanguage, nsresult *aError);
 
   virtual NS_HIDDEN_(already_AddRefed<nsIAtom>)
     LookupCharSet(const char *aCharSet, nsresult *aError);
 
-  virtual NS_HIDDEN_(nsIAtom*) GetLocaleLanguageGroup(nsresult *aError);
+  virtual NS_HIDDEN_(nsIAtom*) GetLocaleLanguage(nsresult *aError);
+
+  virtual NS_HIDDEN_(nsIAtom*) GetLanguageGroup(nsIAtom *aLanguage,
+                                                nsresult *aError);
 
   nsLanguageAtomService() NS_HIDDEN;
 
 private:
   NS_HIDDEN ~nsLanguageAtomService() { }
 
 protected:
   NS_HIDDEN_(nsresult) InitLangGroupTable();
 
   nsCOMPtr<nsICharsetConverterManager> mCharSets;
-  nsInterfaceHashtable<nsStringHashKey, nsIAtom> mLangs;
+  nsInterfaceHashtable<nsISupportsHashKey, nsIAtom> mLangToGroup;
   nsCOMPtr<nsIStringBundle> mLangGroups;
-  nsCOMPtr<nsIAtom> mLocaleLangGroup;
+  nsCOMPtr<nsIAtom> mLocaleLanguage;
 };
--- a/intl/uconv/src/charsetData.properties
+++ b/intl/uconv/src/charsetData.properties
@@ -80,16 +80,34 @@ iso-8859-8.notForOutgoing               
 iso-2022-kr.notForOutgoing              = true
 x-windows-949.notForOutgoing            = true
 x-johab.notForOutgoing                  = true
 
 
 // XXX : there are some entries only necessary for Gtk/Xlib builds
 // to map  XLFD registry-encoding pairs to langGroups. they can be
 // removed once bug 215537 is fixed.
+
+// XXX : todo: move to something based on BCP 47 (RFC 5646);
+// these should primarily specify script (and sometimes region),
+// but NOT language.
+// e.g. x-western      -> *-Latn-155 (Western Europe)
+//      x-central-euro -> *-Latn-151 (Eastern Europe)
+//      x-baltic       -> *-Latn-154 (Northern Europe)
+//      x-cyrillic     -> *-Cyrl
+//      zh-TW          -> *-Hant-TW
+//      zh-HK          -> *-Hant-HK
+//      zh-CN          -> *-Hans
+//      ja             -> *-Jpan
+//      ko             -> *-Hang
+//      tr             -> *-Latn-TR
+//      he             -> *-Hebr
+//      ar             -> *-Arab
+// etc
+
 adobe-symbol-encoding.LangGroup    = el
 armscii-8.LangGroup                = x-armn
 big5.LangGroup                     = zh-TW
 x-x-big5.LangGroup                 = zh-TW
 big5-hkscs.LangGroup               = zh-HK
 euc-jp.LangGroup                   = ja
 euc-kr.LangGroup                   = ko
 gb2312.LangGroup                   = zh-CN
--- a/intl/uconv/src/nsCharsetConverterManager.cpp
+++ b/intl/uconv/src/nsCharsetConverterManager.cpp
@@ -428,13 +428,15 @@ nsCharsetConverterManager::GetCharsetLan
     rv = LoadExtensibleBundle(NS_DATA_BUNDLE_CATEGORY, &mDataBundle);
     if (NS_FAILED(rv))
       return rv;
   }
 
   nsAutoString langGroup;
   rv = GetBundleValue(mDataBundle, aCharset, NS_LITERAL_STRING(".LangGroup"), langGroup);
 
-  if (NS_SUCCEEDED(rv))
+  if (NS_SUCCEEDED(rv)) {
+    ToLowerCase(langGroup); // use lowercase for all language atoms
     *aResult = NS_NewAtom(langGroup);
+  }
 
   return rv;
 }
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -1645,17 +1645,17 @@ nsresult
 nsLayoutUtils::GetFontMetricsForStyleContext(nsStyleContext* aStyleContext,
                                              nsIFontMetrics** aFontMetrics)
 {
   // pass the user font set object into the device context to pass along to CreateFontGroup
   gfxUserFontSet* fs = aStyleContext->PresContext()->GetUserFontSet();
   
   return aStyleContext->PresContext()->DeviceContext()->GetMetricsFor(
                   aStyleContext->GetStyleFont()->mFont,
-                  aStyleContext->GetStyleVisibility()->mLangGroup,
+                  aStyleContext->GetStyleVisibility()->mLanguage,
                   fs, *aFontMetrics);
 }
 
 nsIFrame*
 nsLayoutUtils::FindChildContainingDescendant(nsIFrame* aParent, nsIFrame* aDescendantFrame)
 {
   nsIFrame* result = aDescendantFrame;
 
@@ -3124,17 +3124,17 @@ nsLayoutUtils::GetWholeImageDestination(
 }
 
 void
 nsLayoutUtils::SetFontFromStyle(nsIRenderingContext* aRC, nsStyleContext* aSC) 
 {
   const nsStyleFont* font = aSC->GetStyleFont();
   const nsStyleVisibility* visibility = aSC->GetStyleVisibility();
 
-  aRC->SetFont(font->mFont, visibility->mLangGroup,
+  aRC->SetFont(font->mFont, visibility->mLanguage,
                aSC->PresContext()->GetUserFontSet());
 }
 
 static PRBool NonZeroStyleCoord(const nsStyleCoord& aCoord)
 {
   switch (aCoord.GetUnit()) {
   case eStyleUnit_Percent:
     return aCoord.GetPercentValue() > 0;
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -311,17 +311,17 @@ nsPresContext::~nsPresContext()
                                          nsPresContext::PrefChangedCallback,
                                          this);
   nsContentUtils::UnregisterPrefCallback("layout.css.devPixelsPerPx",
                                          nsPresContext::PrefChangedCallback,
                                          this);
 
   NS_IF_RELEASE(mDeviceContext);
   NS_IF_RELEASE(mLookAndFeel);
-  NS_IF_RELEASE(mLangGroup);
+  NS_IF_RELEASE(mLanguage);
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsPresContext)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPresContext)
    NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
    NS_INTERFACE_MAP_ENTRY(nsIObserver)
 NS_INTERFACE_MAP_END
@@ -341,17 +341,17 @@ TraverseImageLoader(const void * aKey, n
   return PL_DHASH_NEXT;
 }
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsPresContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDeviceContext); // worth bothering?
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mEventManager);
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLookAndFeel); // a service
-  // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLangGroup); // an atom
+  // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mLanguage); // an atom
 
   for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
     tmp->mImageLoaders[i].Enumerate(TraverseImageLoader, &cb);
 
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTheme); // a service
   // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLangService); // a service
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrintSettings);
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrefChangedTimer);
@@ -364,17 +364,17 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
     // unclear if these are needed, but can't hurt
     tmp->mEventManager->NotifyDestroyPresContext(tmp);
     tmp->mEventManager->SetPresContext(nsnull);
 
     NS_RELEASE(tmp->mEventManager);
   }
 
   // NS_RELEASE(tmp->mLookAndFeel); // a service
-  // NS_RELEASE(tmp->mLangGroup); // an atom
+  // NS_RELEASE(tmp->mLanguage); // an atom
 
   // NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTheme); // a service
   // NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLangService); // a service
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrintSettings);
   if (tmp->mPrefChangedTimer)
   {
     tmp->mPrefChangedTimer->Cancel();
     tmp->mPrefChangedTimer = nsnull;
@@ -427,19 +427,24 @@ nsPresContext::GetFontPreferences()
   font.size.[generic].[langGroup] = integer - settable by the user
   font.size-adjust.[generic].[langGroup] = "float" - settable by the user
   font.minimum-size.[langGroup] = integer - settable by the user
   */
 
   mDefaultVariableFont.size = CSSPixelsToAppUnits(16);
   mDefaultFixedFont.size = CSSPixelsToAppUnits(13);
 
+  // the font prefs are based on langGroup, not actual language
   const char *langGroup = "x-western"; // Assume x-western is safe...
-  if (mLangGroup) {
-    mLangGroup->GetUTF8String(&langGroup);
+  if (mLanguage && mLangService) {
+    nsresult rv;
+    nsIAtom *group = mLangService->GetLanguageGroup(mLanguage, &rv);
+    if (NS_SUCCEEDED(rv) && group) {
+      group->GetUTF8String(&langGroup);
+    }
   }
 
   nsCAutoString pref;
 
   // get the current applicable font-size unit
   enum {eUnit_unknown = -1, eUnit_px, eUnit_pt};
   PRInt32 unit = eUnit_px;
 
@@ -995,24 +1000,25 @@ nsPresContext::SetShell(nsIPresShell* aS
     }
   }
 }
 
 void
 nsPresContext::UpdateCharSet(const nsAFlatCString& aCharSet)
 {
   if (mLangService) {
-    NS_IF_RELEASE(mLangGroup);
-    mLangGroup = mLangService->LookupCharSet(aCharSet.get()).get();  // addrefs
+    NS_IF_RELEASE(mLanguage);
+    mLanguage = mLangService->LookupCharSet(aCharSet.get()).get();  // addrefs
+    // this will be a language group (or script) code rather than a true language code
 
     // bug 39570: moved from nsLanguageAtomService::LookupCharSet()
 #if !defined(XP_BEOS) 
-    if (mLangGroup == nsGkAtoms::Unicode) {
-      NS_RELEASE(mLangGroup);
-      NS_IF_ADDREF(mLangGroup = mLangService->GetLocaleLanguageGroup()); 
+    if (mLanguage == nsGkAtoms::Unicode) {
+      NS_RELEASE(mLanguage);
+      NS_IF_ADDREF(mLanguage = mLangService->GetLocaleLanguage()); 
     }
 #endif
     GetFontPreferences();
   }
 #ifdef IBMBIDI
   //ahmed
 
   switch (GET_BIDI_OPTION_TEXTTYPE(GetBidi())) {
@@ -1194,17 +1200,17 @@ nsPresContext::SetImageAnimationModeExte
 {
   SetImageAnimationModeInternal(aMode);
 }
 
 already_AddRefed<nsIFontMetrics>
 nsPresContext::GetMetricsFor(const nsFont& aFont, PRBool aUseUserFontSet)
 {
   nsIFontMetrics* metrics = nsnull;
-  mDeviceContext->GetMetricsFor(aFont, mLangGroup,
+  mDeviceContext->GetMetricsFor(aFont, mLanguage,
                                 aUseUserFontSet ? GetUserFontSet() : nsnull,
                                 metrics);
   return metrics;
 }
 
 const nsFont*
 nsPresContext::GetDefaultFont(PRUint8 aFontID) const
 {
--- a/layout/base/nsPresContext.h
+++ b/layout/base/nsPresContext.h
@@ -533,17 +533,17 @@ public:
   * in print preview.
   * XXX Temporary: see http://wiki.mozilla.org/Gecko:PrintPreview
   */
   float GetPrintPreviewScale() { return mPPScale; }
   void SetPrintPreviewScale(float aScale) { mPPScale = aScale; }
 
   nsIDeviceContext* DeviceContext() { return mDeviceContext; }
   nsIEventStateManager* EventStateManager() { return mEventManager; }
-  nsIAtom* GetLangGroup() { return mLangGroup; }
+  nsIAtom* GetLanguage() { return mLanguage; }
 
   float TextZoom() { return mTextZoom; }
   void SetTextZoom(float aZoom) {
     if (aZoom == mTextZoom)
       return;
 
     mTextZoom = aZoom;
     if (HasCachedStyleData()) {
@@ -989,17 +989,23 @@ protected:
   nsIEventStateManager* mEventManager;  // [STRONG]
   nsILookAndFeel*       mLookAndFeel;   // [STRONG]
   nsRefPtr<nsRefreshDriver> mRefreshDriver;
   nsRefPtr<nsTransitionManager> mTransitionManager;
   nsIAtom*              mMedium;        // initialized by subclass ctors;
                                         // weak pointer to static atom
 
   nsILinkHandler*       mLinkHandler;   // [WEAK]
-  nsIAtom*              mLangGroup;     // [STRONG]
+
+  // Formerly mLangGroup; moving from charset-oriented langGroup to
+  // maintaining actual language settings everywhere (see bug 524107).
+  // This may in fact hold a langGroup such as x-western rather than
+  // a specific language, however (e.g, if it is inferred from the
+  // charset rather than explicitly specified as a lang attribute).
+  nsIAtom*              mLanguage;      // [STRONG]
 
   nsRefPtrHashtable<nsVoidPtrHashKey, nsImageLoader>
                         mImageLoaders[IMAGE_LOAD_TYPE_COUNT];
 
   nsWeakPtr             mContainer;
 
   float                 mTextZoom;      // Text zoom, defaults to 1.0
   float                 mFullZoom;      // Page zoom, defaults to 1.0
--- a/layout/generic/nsPageFrame.cpp
+++ b/layout/generic/nsPageFrame.cpp
@@ -501,17 +501,17 @@ nsPageFrame::PaintHeaderFooter(nsIRender
 
   nsRect rect(aPt.x, aPt.y, mRect.width - mPD->mShadowSize.width,
               mRect.height - mPD->mShadowSize.height);
 
   aRenderingContext.SetColor(NS_RGB(0,0,0));
 
   // Get the FontMetrics to determine width.height of strings
   nsCOMPtr<nsIFontMetrics> fontMet;
-  pc->DeviceContext()->GetMetricsFor(*mPD->mHeadFootFont, nsnull,
+  pc->DeviceContext()->GetMetricsFor(*mPD->mHeadFootFont,
                                      pc->GetUserFontSet(),
                                      *getter_AddRefs(fontMet));
 
   aRenderingContext.SetFont(fontMet);
 
   nscoord ascent = 0;
   nscoord visibleHeight = 0;
   if (fontMet) {
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -1339,17 +1339,17 @@ BuildTextRunsScanner::ContinueTextRunAcr
 
   nsStyleContext* sc2 = aFrame2->GetStyleContext();
   if (sc1 == sc2)
     return PR_TRUE;
   const nsStyleFont* fontStyle1 = sc1->GetStyleFont();
   const nsStyleFont* fontStyle2 = sc2->GetStyleFont();
   const nsStyleText* textStyle2 = sc2->GetStyleText();
   return fontStyle1->mFont.BaseEquals(fontStyle2->mFont) &&
-    sc1->GetStyleVisibility()->mLangGroup == sc2->GetStyleVisibility()->mLangGroup &&
+    sc1->GetStyleVisibility()->mLanguage == sc2->GetStyleVisibility()->mLanguage &&
     nsLayoutUtils::GetTextRunFlagsForStyle(sc1, textStyle1, fontStyle1) ==
       nsLayoutUtils::GetTextRunFlagsForStyle(sc2, textStyle2, fontStyle2);
 }
 
 void BuildTextRunsScanner::ScanFrame(nsIFrame* aFrame)
 {
   // First check if we can extend the current mapped frame block. This is common.
   if (mMappedFlows.Length() > 0) {
@@ -1865,17 +1865,17 @@ HasCompressedLeadingWhitespace(nsTextFra
 }
 
 void
 BuildTextRunsScanner::SetupBreakSinksForTextRun(gfxTextRun* aTextRun,
                                                 PRBool aIsExistingTextRun,
                                                 PRBool aSuppressSink)
 {
   // textruns have uniform language
-  nsIAtom* lang = mMappedFlows[0].mStartFrame->GetStyleVisibility()->mLangGroup;
+  nsIAtom* language = mMappedFlows[0].mStartFrame->GetStyleVisibility()->mLanguage;
   // We keep this pointed at the skip-chars data for the current mappedFlow.
   // This lets us cheaply check whether the flow has compressed initial
   // whitespace...
   gfxSkipCharsIterator iter(aTextRun->GetSkipChars());
 
   PRUint32 i;
   for (i = 0; i < mMappedFlows.Length(); ++i) {
     MappedFlow* mappedFlow = &mMappedFlows[i];
@@ -1913,20 +1913,20 @@ BuildTextRunsScanner::SetupBreakSinksFor
     if (HasCompressedLeadingWhitespace(startFrame, textStyle,
                                        mappedFlow->GetContentEnd(), iter)) {
       mLineBreaker.AppendInvisibleWhitespace(flags);
     }
 
     if (length > 0) {
       BreakSink* sink = aSuppressSink ? nsnull : (*breakSink).get();
       if (aTextRun->GetFlags() & gfxFontGroup::TEXT_IS_8BIT) {
-        mLineBreaker.AppendText(lang, aTextRun->GetText8Bit() + offset,
+        mLineBreaker.AppendText(language, aTextRun->GetText8Bit() + offset,
                                 length, flags, sink);
       } else {
-        mLineBreaker.AppendText(lang, aTextRun->GetTextUnicode() + offset,
+        mLineBreaker.AppendText(language, aTextRun->GetTextUnicode() + offset,
                                 length, flags, sink);
       }
     }
     
     iter = iterNext;
   }
 }
 
@@ -2156,23 +2156,26 @@ static PRInt32 FindChar(const nsTextFrag
       const void* p = memchr(str, ch, aLength);
       if (p)
         return (static_cast<const char*>(p) - str) + aOffset;
     }
   }
   return -1;
 }
 
-static PRBool IsChineseJapaneseLangGroup(nsIFrame* aFrame)
-{
-  nsIAtom* langGroup = aFrame->GetStyleVisibility()->mLangGroup;
-  return langGroup == nsGkAtoms::Japanese
-      || langGroup == nsGkAtoms::Chinese
-      || langGroup == nsGkAtoms::Taiwanese
-      || langGroup == nsGkAtoms::HongKongChinese;
+static PRBool IsChineseOrJapanese(nsIFrame* aFrame)
+{
+  nsIAtom* language = aFrame->GetStyleVisibility()->mLanguage;
+  if (!language) {
+    return PR_FALSE;
+  }
+  const char *lang;
+  language->GetUTF8String(&lang);
+  return (!strncmp(lang, "ja", 2) || !strncmp(lang, "zh", 2)) &&
+         (lang[2] == '\0' || lang[2] == '-');
 }
 
 #ifdef DEBUG
 static PRBool IsInBounds(const gfxSkipCharsIterator& aStart, PRInt32 aContentLength,
                          PRUint32 aOffset, PRUint32 aLength) {
   if (aStart.GetSkippedOffset() > aOffset)
     return PR_FALSE;
   if (aContentLength == PR_INT32_MAX)
@@ -2322,17 +2325,17 @@ protected:
 PRUint32
 PropertyProvider::ComputeJustifiableCharacters(PRInt32 aOffset, PRInt32 aLength)
 {
   // Scan non-skipped characters and count justifiable chars.
   nsSkipCharsRunIterator
     run(mStart, nsSkipCharsRunIterator::LENGTH_INCLUDES_SKIPPED, aLength);
   run.SetOriginalOffset(aOffset);
   PRUint32 justifiableChars = 0;
-  PRBool isCJK = IsChineseJapaneseLangGroup(mFrame);
+  PRBool isCJK = IsChineseOrJapanese(mFrame);
   while (run.NextRun()) {
     PRInt32 i;
     for (i = 0; i < run.GetRunLength(); ++i) {
       justifiableChars +=
         IsJustifiableCharacter(mFrag, run.GetOriginalOffset() + i, isCJK);
     }
   }
   return justifiableChars;
@@ -2447,17 +2450,17 @@ PropertyProvider::GetSpacingInternal(PRU
     }
   }
 
   // Now add in justification spacing
   if (mJustificationSpacing) {
     gfxFloat halfJustificationSpace = mJustificationSpacing/2;
     // Scan non-skipped characters and adjust justifiable chars, adding
     // justification space on either side of the cluster
-    PRBool isCJK = IsChineseJapaneseLangGroup(mFrame);
+    PRBool isCJK = IsChineseOrJapanese(mFrame);
     gfxSkipCharsIterator justificationStart(mStart), justificationEnd(mStart);
     FindJustificationRange(&justificationStart, &justificationEnd);
 
     nsSkipCharsRunIterator
       run(start, nsSkipCharsRunIterator::LENGTH_UNSKIPPED_ONLY, aLength);
     while (run.NextRun()) {
       PRInt32 i;
       gfxSkipCharsIterator iter = run.GetPos();
@@ -6594,17 +6597,17 @@ nsTextFrame::TrimTrailingWhiteSpace(nsIR
     }
   }
 
   if (!result.mLastCharIsJustifiable &&
       (GetStateBits() & TEXT_JUSTIFICATION_ENABLED)) {
     // Check if any character in the last cluster is justifiable
     PropertyProvider provider(mTextRun, textStyle, frag, this, start, contentLength,
                               nsnull, 0);
-    PRBool isCJK = IsChineseJapaneseLangGroup(this);
+    PRBool isCJK = IsChineseOrJapanese(this);
     gfxSkipCharsIterator justificationStart(start), justificationEnd(trimmedEndIter);
     provider.FindJustificationRange(&justificationStart, &justificationEnd);
 
     PRInt32 i;
     for (i = justificationEnd.GetOriginalOffset(); i < trimmed.GetEnd(); ++i) {
       if (IsJustifiableCharacter(frag, i, isCJK)) {
         result.mLastCharIsJustifiable = PR_TRUE;
       }
--- a/layout/mathml/nsMathMLChar.cpp
+++ b/layout/mathml/nsMathMLChar.cpp
@@ -1166,17 +1166,17 @@ SetFontFamily(nsPresContext*       aPres
               const nsGlyphTable*  aGlyphTable,
               const nsGlyphCode&   aGlyphCode,
               const nsAString&     aDefaultFamily)
 {
   const nsAString& family =
     aGlyphCode.font ? aGlyphTable->FontNameFor(aGlyphCode) : aDefaultFamily;
   if (! family.Equals(aFont.name)) {
     aFont.name = family;
-    aRenderingContext.SetFont(aFont, nsnull, aPresContext->GetUserFontSet());
+    aRenderingContext.SetFont(aFont, aPresContext->GetUserFontSet());
   }
 }
 
 class nsMathMLChar::StretchEnumContext {
 public:
   StretchEnumContext(nsMathMLChar*        aChar,
                      nsPresContext*       aPresContext,
                      nsIRenderingContext& aRenderingContext,
@@ -1579,19 +1579,19 @@ nsMathMLChar::StretchInternal(nsPresCont
   }
 
   // Don't modify this nsMathMLChar when doing GetMaxWidth()
   PRBool maxWidth = (NS_STRETCH_MAXWIDTH & aStretchHint) != 0;
   if (!maxWidth) {
     // Record the families in case there is no stretch.  But don't bother
     // storing families when they are just those from the StyleContext.
     mFamily = families;
-  }    
+  }
 
-  aRenderingContext.SetFont(font, nsnull, aPresContext->GetUserFontSet());
+  aRenderingContext.SetFont(font, aPresContext->GetUserFontSet());
   nsresult rv =
     aRenderingContext.GetBoundingMetrics(mData.get(), PRUint32(mData.Length()),
                                          aDesiredStretchSize);
   if (NS_FAILED(rv)) {
     NS_WARNING("GetBoundingMetrics failed");
     return rv;
   }
 
@@ -2091,17 +2091,17 @@ nsMathMLChar::PaintForeground(nsPresCont
       GetColor(nsILookAndFeel::eColor_TextSelectForeground, fgColor);
   }
   aRenderingContext.SetColor(fgColor);
 
   nsFont theFont(styleContext->GetStyleFont()->mFont);
   if (! mFamily.IsEmpty()) {
     theFont.name = mFamily;
   }
-  aRenderingContext.SetFont(theFont, nsnull, aPresContext->GetUserFontSet());
+  aRenderingContext.SetFont(theFont, aPresContext->GetUserFontSet());
 
   if (NS_STRETCH_DIRECTION_UNSUPPORTED == mDirection) {
     // normal drawing if there is nothing special about this char ...
     // Grab some metrics to adjust the placements ...
     PRUint32 len = PRUint32(mData.Length());
 //printf("Painting %04X like a normal char\n", mData[0]);
 //aRenderingContext.SetColor(NS_RGB(255,0,0));
     aRenderingContext.DrawString(mData.get(), len, mRect.x + aPt.x,
--- a/layout/mathml/nsMathMLmencloseFrame.cpp
+++ b/layout/mathml/nsMathMLmencloseFrame.cpp
@@ -369,17 +369,17 @@ nsMathMLmencloseFrame::PlaceInternal(nsI
   nscoord longdivAscent = 0, longdivDescent = 0;
   nscoord psi = 0;
 
   ///////////////
   // Thickness of bars and font metrics
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
   nsCOMPtr<nsIFontMetrics> fm;
   nscoord mEmHeight;
-  aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull,
+  aRenderingContext.SetFont(GetStyleFont()->mFont,
                             PresContext()->GetUserFontSet());
   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
   GetRuleThickness(aRenderingContext, fm, mRuleThickness);
   GetEmHeight(fm, mEmHeight);
 
   nsBoundingMetrics bmOne;
   aRenderingContext.GetBoundingMetrics(NS_LITERAL_STRING("1").get(), 1, bmOne);
 
--- a/layout/mathml/nsMathMLmfencedFrame.cpp
+++ b/layout/mathml/nsMathMLmfencedFrame.cpp
@@ -245,17 +245,17 @@ nsMathMLmfencedFrame::Reflow(nsPresConte
   nsresult rv;
   aDesiredSize.width = aDesiredSize.height = 0;
   aDesiredSize.ascent = 0;
   aDesiredSize.mBoundingMetrics.Clear();
 
   PRInt32 i;
   nsCOMPtr<nsIFontMetrics> fm;
   const nsStyleFont* font = GetStyleFont();
-  aReflowState.rendContext->SetFont(font->mFont, nsnull,
+  aReflowState.rendContext->SetFont(font->mFont,
                                     aPresContext->GetUserFontSet());
   aReflowState.rendContext->GetFontMetrics(*getter_AddRefs(fm));
   nscoord axisHeight, em;
   GetAxisHeight(*aReflowState.rendContext, fm, axisHeight);
   GetEmHeight(fm, em);
   // leading to be left at the top and the bottom of stretched chars
   nscoord leading = NSToCoordRound(0.2f * em); 
 
--- a/layout/mathml/nsMathMLmfracFrame.cpp
+++ b/layout/mathml/nsMathMLmfracFrame.cpp
@@ -263,17 +263,17 @@ nsMathMLmfracFrame::PlaceInternal(nsIRen
     return ReflowError(aRenderingContext, aDesiredSize);
   }
   GetReflowAndBoundingMetricsFor(frameNum, sizeNum, bmNum);
   GetReflowAndBoundingMetricsFor(frameDen, sizeDen, bmDen);
 
   nsPresContext* presContext = PresContext();
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
 
-  aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull,
+  aRenderingContext.SetFont(GetStyleFont()->mFont,
                             presContext->GetUserFontSet());
   nsCOMPtr<nsIFontMetrics> fm;
   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
 
   nscoord defaultRuleThickness, axisHeight;
   GetRuleThickness(aRenderingContext, fm, defaultRuleThickness);
   GetAxisHeight(aRenderingContext, fm, axisHeight);
 
--- a/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
+++ b/layout/mathml/nsMathMLmmultiscriptsFrame.cpp
@@ -156,17 +156,17 @@ nsMathMLmmultiscriptsFrame::Place(nsIRen
   // Initialize super/sub shifts that
   // depend only on the current font
   ////////////////////////////////////////
 
   ProcessAttributes();
 
   // get x-height (an ex)
   const nsStyleFont* font = GetStyleFont();
-  aRenderingContext.SetFont(font->mFont, nsnull,
+  aRenderingContext.SetFont(font->mFont,
                             PresContext()->GetUserFontSet());
   nsCOMPtr<nsIFontMetrics> fm;
   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
 
   nscoord xHeight;
   fm->GetXHeight (xHeight);
 
   nscoord ruleSize;
--- a/layout/mathml/nsMathMLmoFrame.cpp
+++ b/layout/mathml/nsMathMLmoFrame.cpp
@@ -628,17 +628,17 @@ nsMathMLmoFrame::Stretch(nsIRenderingCon
     return NS_OK;
   }
   mPresentationData.flags |= NS_MATHML_STRETCH_DONE;
 
   nsIFrame* firstChild = mFrames.FirstChild();
 
   // get the axis height;
   nsCOMPtr<nsIFontMetrics> fm;
-  aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull,
+  aRenderingContext.SetFont(GetStyleFont()->mFont,
                             PresContext()->GetUserFontSet());
   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
   nscoord axisHeight, height;
   GetAxisHeight(aRenderingContext, fm, axisHeight);
 
   // get the leading to be left at the top and the bottom of the stretched char
   // this seems more reliable than using fm->GetLeading() on suspicious fonts               
   nscoord em;
--- a/layout/mathml/nsMathMLmoverFrame.cpp
+++ b/layout/mathml/nsMathMLmoverFrame.cpp
@@ -277,17 +277,17 @@ nsMathMLmoverFrame::Place(nsIRenderingCo
   GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
   GetReflowAndBoundingMetricsFor(overFrame, overSize, bmOver);
 
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
 
   ////////////////////
   // Place Children
 
-  aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull,
+  aRenderingContext.SetFont(GetStyleFont()->mFont,
                             PresContext()->GetUserFontSet());
   nsCOMPtr<nsIFontMetrics> fm;
   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
 
   nscoord xHeight = 0;
   fm->GetXHeight (xHeight);
 
   nscoord ruleThickness;
--- a/layout/mathml/nsMathMLmrootFrame.cpp
+++ b/layout/mathml/nsMathMLmrootFrame.cpp
@@ -254,17 +254,17 @@ nsMathMLmrootFrame::Reflow(nsPresContext
     // Call DidReflow() for the child frames we successfully did reflow.
     DidReflowChildren(mFrames.FirstChild(), childFrame);
     return rv;
   }
 
   ////////////
   // Prepare the radical symbol and the overline bar
 
-  renderingContext.SetFont(GetStyleFont()->mFont, nsnull,
+  renderingContext.SetFont(GetStyleFont()->mFont,
                            aPresContext->GetUserFontSet());
   nsCOMPtr<nsIFontMetrics> fm;
   renderingContext.GetFontMetrics(*getter_AddRefs(fm));
 
   // For radical glyphs from TeX fonts and some of the radical glyphs from
   // Mathematica fonts, the thickness of the overline can be obtained from the
   // ascent of the glyph.  Most fonts however have radical glyphs above the
   // baseline so no assumption can be made about the meaning of the ascent.
--- a/layout/mathml/nsMathMLmsubsupFrame.cpp
+++ b/layout/mathml/nsMathMLmsubsupFrame.cpp
@@ -189,17 +189,17 @@ nsMathMLmsubsupFrame::PlaceSubSupScript(
   //////////////////////////////////////////////////
 
   // subScriptShift{1,2}
   // = minimum amount to shift the subscript down
   // = sub{1,2} in TeXbook
   // subScriptShift1 = subscriptshift attribute * x-height
   nscoord subScriptShift1, subScriptShift2;
 
-  aRenderingContext.SetFont(baseFrame->GetStyleFont()->mFont, nsnull,
+  aRenderingContext.SetFont(baseFrame->GetStyleFont()->mFont,
                             aPresContext->GetUserFontSet());
   nsCOMPtr<nsIFontMetrics> fm;
   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
 
   // get x-height (an ex)
   nscoord xHeight;
   fm->GetXHeight (xHeight);
 
--- a/layout/mathml/nsMathMLmtableFrame.cpp
+++ b/layout/mathml/nsMathMLmtableFrame.cpp
@@ -604,17 +604,17 @@ nsMathMLmtableOuterFrame::Reflow(nsPresC
         }
       }
       // in other situations, fallback to center
       aDesiredSize.ascent = dy + height/2;
       break;
     case eAlign_axis:
     default: {
       // XXX should instead use style data from the row of reference here ?
-      aReflowState.rendContext->SetFont(GetStyleFont()->mFont, nsnull,
+      aReflowState.rendContext->SetFont(GetStyleFont()->mFont,
                                         aPresContext->GetUserFontSet());
       nsCOMPtr<nsIFontMetrics> fm;
       aReflowState.rendContext->GetFontMetrics(*getter_AddRefs(fm));
       nscoord axisHeight;
       GetAxisHeight(*aReflowState.rendContext, fm, axisHeight);
       if (rowFrame) {
         // anchor the table on the axis of the row of reference
         // XXX fallback to baseline because it is a hard problem
--- a/layout/mathml/nsMathMLmunderFrame.cpp
+++ b/layout/mathml/nsMathMLmunderFrame.cpp
@@ -274,17 +274,17 @@ nsMathMLmunderFrame::Place(nsIRenderingC
   GetReflowAndBoundingMetricsFor(baseFrame, baseSize, bmBase);
   GetReflowAndBoundingMetricsFor(underFrame, underSize, bmUnder);
 
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
 
   ////////////////////
   // Place Children
 
-  aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull,
+  aRenderingContext.SetFont(GetStyleFont()->mFont,
                             PresContext()->GetUserFontSet());
   nsCOMPtr<nsIFontMetrics> fm;
   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
 
   nscoord xHeight = 0;
   fm->GetXHeight (xHeight);
 
   nscoord ruleThickness;
--- a/layout/mathml/nsMathMLmunderoverFrame.cpp
+++ b/layout/mathml/nsMathMLmunderoverFrame.cpp
@@ -315,17 +315,17 @@ nsMathMLmunderoverFrame::Place(nsIRender
   GetReflowAndBoundingMetricsFor(underFrame, underSize, bmUnder);
   GetReflowAndBoundingMetricsFor(overFrame, overSize, bmOver);
 
   nscoord onePixel = nsPresContext::CSSPixelsToAppUnits(1);
 
   ////////////////////
   // Place Children
 
-  aRenderingContext.SetFont(GetStyleFont()->mFont, nsnull,
+  aRenderingContext.SetFont(GetStyleFont()->mFont,
                             PresContext()->GetUserFontSet());
   nsCOMPtr<nsIFontMetrics> fm;
   aRenderingContext.GetFontMetrics(*getter_AddRefs(fm));
 
   nscoord xHeight = 0;
   fm->GetXHeight (xHeight);
 
   nscoord ruleThickness;
--- a/layout/style/nsRuleNode.cpp
+++ b/layout/style/nsRuleNode.cpp
@@ -66,16 +66,17 @@
 #include "nsStyleContext.h"
 #include "nsStyleSet.h"
 #include "nsSize.h"
 #include "imgIRequest.h"
 #include "nsRuleData.h"
 #include "nsILanguageAtomService.h"
 #include "nsIStyleRule.h"
 #include "nsBidiUtils.h"
+#include "nsUnicharUtils.h"
 #include "nsStyleStructInlines.h"
 #include "nsStyleTransformMatrix.h"
 #include "nsCSSKeywords.h"
 #include "nsCSSProps.h"
 #include "nsTArray.h"
 #include "nsContentUtils.h"
 
 #define NS_SET_IMAGE_REQUEST(method_, context_, request_)                   \
@@ -4204,17 +4205,19 @@ nsRuleNode::ComputeVisibilityData(void* 
   if (eCSSUnit_Ident == displayData.mLang.GetUnit()) {
     if (!gLangService) {
       CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID, &gLangService);
     }
 
     if (gLangService) {
       nsAutoString lang;
       displayData.mLang.GetStringValue(lang);
-      visibility->mLangGroup = gLangService->LookupLanguage(lang);
+
+      ToLowerCase(lang);
+      visibility->mLanguage = do_GetAtom(lang);
     }
   }
 
   COMPUTE_END_INHERITED(Visibility, visibility)
 }
 
 const void*
 nsRuleNode::ComputeColorData(void* aStartStruct,
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -1945,34 +1945,34 @@ nsStyleVisibility::nsStyleVisibility(nsP
 {
   MOZ_COUNT_CTOR(nsStyleVisibility);
   PRUint32 bidiOptions = aPresContext->GetBidi();
   if (GET_BIDI_OPTION_DIRECTION(bidiOptions) == IBMBIDI_TEXTDIRECTION_RTL)
     mDirection = NS_STYLE_DIRECTION_RTL;
   else
     mDirection = NS_STYLE_DIRECTION_LTR;
 
-  mLangGroup = aPresContext->GetLangGroup();
+  mLanguage = aPresContext->GetLanguage();
   mVisible = NS_STYLE_VISIBILITY_VISIBLE;
   mPointerEvents = NS_STYLE_POINTER_EVENTS_AUTO;
 }
 
 nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
 {
   MOZ_COUNT_CTOR(nsStyleVisibility);
   mDirection = aSource.mDirection;
   mVisible = aSource.mVisible;
-  mLangGroup = aSource.mLangGroup;
+  mLanguage = aSource.mLanguage;
   mPointerEvents = aSource.mPointerEvents;
 } 
 
 nsChangeHint nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) const
 {
   if ((mDirection == aOther.mDirection) &&
-      (mLangGroup == aOther.mLangGroup)) {
+      (mLanguage == aOther.mLanguage)) {
     if ((mVisible == aOther.mVisible)) {
       return NS_STYLE_HINT_NONE;
     }
     if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) || 
         (NS_STYLE_VISIBILITY_COLLAPSE == aOther.mVisible)) {
       return NS_STYLE_HINT_REFLOW;
     }
     return NS_STYLE_HINT_VISUAL;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -1186,17 +1186,17 @@ struct nsStyleVisibility {
   nsChangeHint CalcDifference(const nsStyleVisibility& aOther) const;
 #ifdef DEBUG
   static nsChangeHint MaxDifference();
 #endif
   static PRBool ForceCompare() { return PR_FALSE; }
   
   PRUint8 mDirection;                  // [inherited] see nsStyleConsts.h NS_STYLE_DIRECTION_*
   PRUint8   mVisible;                  // [inherited]
-  nsCOMPtr<nsIAtom> mLangGroup;        // [inherited]
+  nsCOMPtr<nsIAtom> mLanguage;         // [inherited]
   PRUint8 mPointerEvents;              // [inherited] see nsStyleConsts.h
 
   PRBool IsVisible() const {
     return (mVisible == NS_STYLE_VISIBILITY_VISIBLE);
   }
 
   PRBool IsVisibleOrCollapsed() const {
     return ((mVisible == NS_STYLE_VISIBILITY_VISIBLE) ||
--- a/layout/svg/base/src/nsSVGGlyphFrame.cpp
+++ b/layout/svg/base/src/nsSVGGlyphFrame.cpp
@@ -1330,38 +1330,36 @@ nsSVGGlyphFrame::EnsureTextRun(float *aD
     }
 
     // The context scale is the ratio of the length of the transformed
     // diagonal vector (1,1) to the length of the untransformed diagonal
     // (which is sqrt(2)).
     gfxPoint p = m.Transform(gfxPoint(1, 1)) - m.Transform(gfxPoint(0, 0));
     double contextScale = nsSVGUtils::ComputeNormalizedHypotenuse(p.x, p.y);
 
-    nsCAutoString langGroup;
-    nsIAtom *langGroupAtom = mStyleContext->GetStyleVisibility()->mLangGroup;
-    if (langGroupAtom) {
-      const char* lg;
-      langGroupAtom->GetUTF8String(&lg);
-      langGroup.Assign(lg);
+    nsCString language;
+    nsIAtom *languageAtom = mStyleContext->GetStyleVisibility()->mLanguage;
+    if (languageAtom) {
+      languageAtom->ToUTF8String(language);
     }
 
     if (GetStyleSVG()->mTextRendering ==
         NS_STYLE_TEXT_RENDERING_GEOMETRICPRECISION) {
       textRunSize = PRECISE_SIZE;
     } else {
       textRunSize = size*contextScale;
       textRunSize = NS_MAX(textRunSize, double(CLAMP_MIN_SIZE));
       textRunSize = NS_MIN(textRunSize, double(CLAMP_MAX_SIZE));
     }
 
     const nsFont& font = fontData->mFont;
     PRBool printerFont = (presContext->Type() == nsPresContext::eContext_PrintPreview ||
                           presContext->Type() == nsPresContext::eContext_Print);
     gfxFontStyle fontStyle(font.style, font.weight, font.stretch, textRunSize,
-                           langGroup, font.sizeAdjust, font.systemFont,
+                           language, font.sizeAdjust, font.systemFont,
                            font.familyNameQuirks,
                            printerFont);
 
     nsRefPtr<gfxFontGroup> fontGroup =
       gfxPlatform::GetPlatform()->CreateFontGroup(font.name, &fontStyle, presContext->GetUserFontSet());
 
     PRUint32 flags = gfxTextRunFactory::TEXT_NEED_BOUNDING_BOX |
       nsLayoutUtils::GetTextRunFlagsForStyle(GetStyleContext(), GetStyleText(), GetStyleFont());