Add support for unicode-bidi: -moz-plaintext in XUL. Bug 869833, r=roc
authorSimon Montagu <smontagu@smontagu.org>
Mon, 18 Nov 2013 17:24:16 +0200
changeset 156077 04054b2172f3a44e72bb5dbf5d1866a8b6c29733
parent 156076 03c3f2a8510262924bf0a4b4d95d382fe3f6777c
child 156078 ac08f00a8ebcb4fd2af34edf95b9baf0c26c23a8
push id36288
push usersmontagu@mozilla.com
push dateMon, 18 Nov 2013 18:14:35 +0000
treeherdermozilla-inbound@04054b2172f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs869833
milestone28.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Add support for unicode-bidi: -moz-plaintext in XUL. Bug 869833, r=roc
layout/base/nsBidiPresUtils.cpp
layout/base/nsBidiPresUtils.h
layout/base/nsLayoutUtils.cpp
layout/base/nsLayoutUtils.h
layout/xul/base/src/nsTextBoxFrame.cpp
layout/xul/tree/nsTreeBodyFrame.cpp
layout/xul/tree/nsTreeBodyFrame.h
--- a/layout/base/nsBidiPresUtils.cpp
+++ b/layout/base/nsBidiPresUtils.cpp
@@ -54,27 +54,17 @@ struct BidiParagraphData {
   uint8_t             mParagraphDepth;
 
   void Init(nsBlockFrame *aBlockFrame)
   {
     mBidiEngine = new nsBidi();
     mPrevContent = nullptr;
     mParagraphDepth = 0;
 
-    bool styleDirectionIsRTL =
-      (NS_STYLE_DIRECTION_RTL == aBlockFrame->StyleVisibility()->mDirection);
-    if (aBlockFrame->StyleTextReset()->mUnicodeBidi &
-        NS_STYLE_UNICODE_BIDI_PLAINTEXT) {
-      // unicode-bidi: plaintext: the Bidi algorithm will determine the
-      // directionality of the paragraph according to the first strong
-      // directional character, defaulting to LTR if there is none.
-      mParaLevel = NSBIDI_DEFAULT_LTR;
-    } else {
-      mParaLevel = styleDirectionIsRTL ? NSBIDI_RTL : NSBIDI_LTR;
-    }
+    mParaLevel = nsBidiPresUtils::BidiLevelFromStyle(aBlockFrame->StyleContext());
 
     mIsVisual = aBlockFrame->PresContext()->IsVisualMode();
     if (mIsVisual) {
       /**
        * Drill up in content to detect whether this is an element that needs to
        * be rendered with logical order even on visual pages.
        *
        * We always use logical order on form controls, firstly so that text
@@ -1808,32 +1798,32 @@ nsBidiPresUtils::CalculateCharType(nsBid
       aCharType = charType;
     }
   }
   aOffset = offset;
 }
 
 nsresult nsBidiPresUtils::ProcessText(const PRUnichar*       aText,
                                       int32_t                aLength,
-                                      nsBidiDirection        aBaseDirection,
+                                      nsBidiLevel            aBaseLevel,
                                       nsPresContext*         aPresContext,
                                       BidiProcessor&         aprocessor,
                                       Mode                   aMode,
                                       nsBidiPositionResolve* aPosResolve,
                                       int32_t                aPosResolveCount,
                                       nscoord*               aWidth,
                                       nsBidi*                aBidiEngine)
 {
   NS_ASSERTION((aPosResolve == nullptr) != (aPosResolveCount > 0), "Incorrect aPosResolve / aPosResolveCount arguments");
 
   int32_t runCount;
 
   nsAutoString textBuffer(aText, aLength);
 
-  nsresult rv = aBidiEngine->SetPara(aText, aLength, aBaseDirection, nullptr);
+  nsresult rv = aBidiEngine->SetPara(aText, aLength, aBaseLevel, nullptr);
   if (NS_FAILED(rv))
     return rv;
 
   rv = aBidiEngine->CountRuns(&runCount);
   if (NS_FAILED(rv))
     return rv;
 
   nscoord xOffset = 0;
@@ -1848,17 +1838,18 @@ nsresult nsBidiPresUtils::ProcessText(co
   for(int nPosResolve=0; nPosResolve < aPosResolveCount; ++nPosResolve)
   {
     aPosResolve[nPosResolve].visualIndex = kNotFound;
     aPosResolve[nPosResolve].visualLeftTwips = kNotFound;
     aPosResolve[nPosResolve].visualWidth = kNotFound;
   }
 
   for (i = 0; i < runCount; i++) {
-    rv = aBidiEngine->GetVisualRun(i, &start, &length, &aBaseDirection);
+    nsBidiDirection dir;
+    rv = aBidiEngine->GetVisualRun(i, &start, &length, &dir);
     if (NS_FAILED(rv))
       return rv;
 
     rv = aBidiEngine->GetLogicalRun(start, &limit, &level);
     if (NS_FAILED(rv))
       return rv;
 
     int32_t subRunLength = limit - start;
@@ -2057,30 +2048,30 @@ private:
   nsRenderingContext* mTextRunConstructionContext;
   nsPoint mPt;
   const PRUnichar* mText;
   int32_t mLength;
 };
 
 nsresult nsBidiPresUtils::ProcessTextForRenderingContext(const PRUnichar*       aText,
                                                          int32_t                aLength,
-                                                         nsBidiDirection        aBaseDirection,
+                                                         nsBidiLevel            aBaseLevel,
                                                          nsPresContext*         aPresContext,
                                                          nsRenderingContext&   aRenderingContext,
                                                          nsRenderingContext&   aTextRunConstructionContext,
                                                          Mode                   aMode,
                                                          nscoord                aX,
                                                          nscoord                aY,
                                                          nsBidiPositionResolve* aPosResolve,
                                                          int32_t                aPosResolveCount,
                                                          nscoord*               aWidth)
 {
   nsIRenderingContextBidiProcessor processor(&aRenderingContext, &aTextRunConstructionContext, nsPoint(aX, aY));
   nsBidi bidiEngine;
-  return ProcessText(aText, aLength, aBaseDirection, aPresContext, processor,
+  return ProcessText(aText, aLength, aBaseLevel, aPresContext, processor,
                      aMode, aPosResolve, aPosResolveCount, aWidth, &bidiEngine);
 }
 
 /* static */
 void nsBidiPresUtils::WriteReverse(const PRUnichar* aSrc,
                                    uint32_t aSrcLength,
                                    PRUnichar* aDest)
 {
@@ -2192,9 +2183,25 @@ void nsBidiPresUtils::CopyLogicalToVisua
 
   if (aDest.IsEmpty()) {
     // Either there was an error or the source is unidirectional
     //  left-to-right. In either case, just copy source to dest.
     CopyUnicodeTo(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd),
                   aDest);
   }
 }
+
+/* static */
+nsBidiLevel
+nsBidiPresUtils::BidiLevelFromStyle(nsStyleContext* aStyleContext)
+{
+  if (aStyleContext->StyleTextReset()->mUnicodeBidi &
+      NS_STYLE_UNICODE_BIDI_PLAINTEXT) {
+    return NSBIDI_DEFAULT_LTR;
+  }
+
+  if (aStyleContext->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
+    return NSBIDI_RTL;
+  }
+
+  return NSBIDI_LTR;
+}
 #endif // IBMBIDI
--- a/layout/base/nsBidiPresUtils.h
+++ b/layout/base/nsBidiPresUtils.h
@@ -20,16 +20,17 @@
 
 struct BidiParagraphData;
 struct BidiLineData;
 class nsIFrame;
 class nsBlockFrame;
 class nsPresContext;
 class nsRenderingContext;
 class nsBlockInFlowLineIterator;
+class nsStyleContext;
 template<class T> class nsTHashtable;
 
 /**
  * A structure representing some continuation state for each frame on the line,
  * used to determine the first and the last continuation frame for each
  * continuation chain on the line.
  */
 struct nsFrameContinuationState : public nsVoidPtrHashKey
@@ -174,50 +175,57 @@ public:
                                     bool            aIsOddLevel);
 
   /**
    * Reorder plain text using the Unicode Bidi algorithm and send it to
    * a rendering context for rendering.
    *
    * @param[in] aText  the string to be rendered (in logical order)
    * @param aLength the number of characters in the string
-   * @param aBaseDirection the base direction of the string
+   * @param aBaseLevel the base embedding level of the string
+   *  odd values are right-to-left; even values are left-to-right, plus special
+   *  constants as follows (defined in nsBidi.h)
    *  NSBIDI_LTR - left-to-right string
    *  NSBIDI_RTL - right-to-left string
+   *  NSBIDI_DEFAULT_LTR - auto direction determined by first strong character,
+   *                       default is left-to-right
+   *  NSBIDI_DEFAULT_RTL - auto direction determined by first strong character,
+   *                       default is right-to-left
+   *
    * @param aPresContext the presentation context
    * @param aRenderingContext the rendering context to render to
    * @param aTextRunConstructionContext the rendering context to be used to construct the textrun (affects font hinting)
    * @param aX the x-coordinate to render the string
    * @param aY the y-coordinate to render the string
    * @param[in,out] aPosResolve array of logical positions to resolve into visual positions; can be nullptr if this functionality is not required
    * @param aPosResolveCount number of items in the aPosResolve array
    */
   static nsresult RenderText(const PRUnichar*       aText,
                              int32_t                aLength,
-                             nsBidiDirection        aBaseDirection,
+                             nsBidiLevel            aBaseLevel,
                              nsPresContext*         aPresContext,
                              nsRenderingContext&    aRenderingContext,
                              nsRenderingContext&    aTextRunConstructionContext,
                              nscoord                aX,
                              nscoord                aY,
                              nsBidiPositionResolve* aPosResolve = nullptr,
                              int32_t                aPosResolveCount = 0)
   {
-    return ProcessTextForRenderingContext(aText, aLength, aBaseDirection, aPresContext, aRenderingContext,
+    return ProcessTextForRenderingContext(aText, aLength, aBaseLevel, aPresContext, aRenderingContext,
                                           aTextRunConstructionContext, MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nullptr);
   }
   
   static nscoord MeasureTextWidth(const PRUnichar*     aText,
                                   int32_t              aLength,
-                                  nsBidiDirection      aBaseDirection,
+                                  nsBidiLevel          aBaseLevel,
                                   nsPresContext*       aPresContext,
                                   nsRenderingContext&  aRenderingContext)
   {
     nscoord length;
-    nsresult rv = ProcessTextForRenderingContext(aText, aLength, aBaseDirection, aPresContext,
+    nsresult rv = ProcessTextForRenderingContext(aText, aLength, aBaseLevel, aPresContext,
                                                  aRenderingContext, aRenderingContext,
                                                  MODE_MEASURE, 0, 0, nullptr, 0, &length);
     return NS_SUCCEEDED(rv) ? length : 0;
   }
 
   /**
    * Check if a line is reordered, i.e., if the child frames are not
    * all laid out left-to-right.
@@ -273,33 +281,40 @@ public:
   enum Mode { MODE_DRAW, MODE_MEASURE };
 
   /**
    * Reorder plain text using the Unicode Bidi algorithm and send it to
    * a processor for rendering or measuring
    *
    * @param[in] aText  the string to be processed (in logical order)
    * @param aLength the number of characters in the string
-   * @param aBaseDirection the base direction of the string
+   * @param aBaseLevel the base embedding level of the string
+   *  odd values are right-to-left; even values are left-to-right, plus special
+   *  constants as follows (defined in nsBidi.h)
    *  NSBIDI_LTR - left-to-right string
    *  NSBIDI_RTL - right-to-left string
+   *  NSBIDI_DEFAULT_LTR - auto direction determined by first strong character,
+   *                       default is left-to-right
+   *  NSBIDI_DEFAULT_RTL - auto direction determined by first strong character,
+   *                       default is right-to-left
+   *
    * @param aPresContext the presentation context
    * @param aprocessor the bidi processor
    * @param aMode the operation to process
    *  MODE_DRAW - invokes DrawText on the processor for each substring
    *  MODE_MEASURE - does not invoke DrawText on the processor
    *  Note that the string is always measured, regardless of mode
    * @param[in,out] aPosResolve array of logical positions to resolve into
    *  visual positions; can be nullptr if this functionality is not required
    * @param aPosResolveCount number of items in the aPosResolve array
    * @param[out] aWidth Pointer to where the width will be stored (may be null)
    */
   static nsresult ProcessText(const PRUnichar*       aText,
                               int32_t                aLength,
-                              nsBidiDirection        aBaseDirection,
+                              nsBidiLevel            aBaseLevel,
                               nsPresContext*         aPresContext,
                               BidiProcessor&         aprocessor,
                               Mode                   aMode,
                               nsBidiPositionResolve* aPosResolve,
                               int32_t                aPosResolveCount,
                               nscoord*               aWidth,
                               nsBidi*                aBidiEngine);
 
@@ -316,21 +331,35 @@ public:
    * @param aOverride if TRUE, the text has a bidi override, according to
    *                    the direction in aDir
    */
   static void CopyLogicalToVisual(const nsAString& aSource,
                                   nsAString& aDest,
                                   nsBidiLevel aBaseDirection,
                                   bool aOverride);
 
+  /**
+   * Use style attributes to determine the base paragraph level to pass to the
+   * bidi algorithm.
+   *
+   * If |unicode-bidi| is set to "[-moz-]plaintext", returns NSBIDI_DEFAULT_LTR,
+   * in other words the direction is determined from the first strong character
+   * in the text according to rules P2 and P3 of the bidi algorithm, or LTR if
+   * there is no strong character.
+   *
+   * Otherwise returns NSBIDI_LTR or NSBIDI_RTL depending on the value of
+   * |direction|
+   */
+  static nsBidiLevel BidiLevelFromStyle(nsStyleContext* aStyleContext);
+
 private:
   static nsresult
   ProcessTextForRenderingContext(const PRUnichar*       aText,
                                  int32_t                aLength,
-                                 nsBidiDirection        aBaseDirection,
+                                 nsBidiLevel            aBaseLevel,
                                  nsPresContext*         aPresContext,
                                  nsRenderingContext&    aRenderingContext,
                                  nsRenderingContext&    aTextRunConstructionContext,
                                  Mode                   aMode,
                                  nscoord                aX, // DRAW only
                                  nscoord                aY, // DRAW only
                                  nsBidiPositionResolve* aPosResolve,  /* may be null */
                                  int32_t                aPosResolveCount,
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3724,34 +3724,31 @@ nsLayoutUtils::GetSnappedBaselineY(nsIFr
   gfxFloat baseline = gfxFloat(aY) + aAscent;
   gfxRect putativeRect(0, baseline/appUnitsPerDevUnit, 1, 1);
   if (!aContext->UserToDevicePixelSnapped(putativeRect, true))
     return baseline;
   return aContext->DeviceToUser(putativeRect.TopLeft()).y * appUnitsPerDevUnit;
 }
 
 void
-nsLayoutUtils::DrawString(const nsIFrame*      aFrame,
-                          nsRenderingContext* aContext,
-                          const PRUnichar*     aString,
-                          int32_t              aLength,
-                          nsPoint              aPoint,
-                          uint8_t              aDirection)
+nsLayoutUtils::DrawString(const nsIFrame*       aFrame,
+                          nsRenderingContext*   aContext,
+                          const PRUnichar*      aString,
+                          int32_t               aLength,
+                          nsPoint               aPoint,
+                          nsStyleContext*       aStyleContext)
 {
 #ifdef IBMBIDI
   nsresult rv = NS_ERROR_FAILURE;
   nsPresContext* presContext = aFrame->PresContext();
   if (presContext->BidiEnabled()) {
-    if (aDirection == NS_STYLE_DIRECTION_INHERIT) {
-      aDirection = aFrame->StyleVisibility()->mDirection;
-    }
-    nsBidiDirection direction =
-      (NS_STYLE_DIRECTION_RTL == aDirection) ?
-      NSBIDI_RTL : NSBIDI_LTR;
-    rv = nsBidiPresUtils::RenderText(aString, aLength, direction,
+    nsBidiLevel level =
+      nsBidiPresUtils::BidiLevelFromStyle(aStyleContext ?
+                                          aStyleContext : aFrame->StyleContext());
+    rv = nsBidiPresUtils::RenderText(aString, aLength, level,
                                      presContext, *aContext, *aContext,
                                      aPoint.x, aPoint.y);
   }
   if (NS_FAILED(rv))
 #endif // IBMBIDI
   {
     aContext->SetTextRunRTL(false);
     aContext->DrawString(aString, aLength, aPoint.x, aPoint.y);
@@ -3762,22 +3759,20 @@ nscoord
 nsLayoutUtils::GetStringWidth(const nsIFrame*      aFrame,
                               nsRenderingContext* aContext,
                               const PRUnichar*     aString,
                               int32_t              aLength)
 {
 #ifdef IBMBIDI
   nsPresContext* presContext = aFrame->PresContext();
   if (presContext->BidiEnabled()) {
-    const nsStyleVisibility* vis = aFrame->StyleVisibility();
-    nsBidiDirection direction =
-      (NS_STYLE_DIRECTION_RTL == vis->mDirection) ?
-      NSBIDI_RTL : NSBIDI_LTR;
+    nsBidiLevel level =
+      nsBidiPresUtils::BidiLevelFromStyle(aFrame->StyleContext());
     return nsBidiPresUtils::MeasureTextWidth(aString, aLength,
-                                             direction, presContext, *aContext);
+                                             level, presContext, *aContext);
   }
 #endif // IBMBIDI
   aContext->SetTextRunRTL(false);
   return aContext->GetWidth(aString, aLength);
 }
 
 /* static */ void
 nsLayoutUtils::PaintTextShadow(const nsIFrame* aFrame,
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -1140,22 +1140,22 @@ public:
 
   // Get a suitable foreground color for painting aProperty for aFrame.
   static nscolor GetColor(nsIFrame* aFrame, nsCSSProperty aProperty);
 
   // Get a baseline y position in app units that is snapped to device pixels.
   static gfxFloat GetSnappedBaselineY(nsIFrame* aFrame, gfxContext* aContext,
                                       nscoord aY, nscoord aAscent);
 
-  static void DrawString(const nsIFrame*      aFrame,
-                         nsRenderingContext* aContext,
-                         const PRUnichar*     aString,
-                         int32_t              aLength,
-                         nsPoint              aPoint,
-                         uint8_t              aDirection = NS_STYLE_DIRECTION_INHERIT);
+  static void DrawString(const nsIFrame*       aFrame,
+                         nsRenderingContext*   aContext,
+                         const PRUnichar*      aString,
+                         int32_t               aLength,
+                         nsPoint               aPoint,
+                         nsStyleContext*       aStyleContext = nullptr);
 
   static nscoord GetStringWidth(const nsIFrame*      aFrame,
                                 nsRenderingContext* aContext,
                                 const PRUnichar*     aString,
                                 int32_t              aLength);
 
   /**
    * Helper function for drawing text-shadow. The callback's job
--- a/layout/xul/base/src/nsTextBoxFrame.cpp
+++ b/layout/xul/base/src/nsTextBoxFrame.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsTextBoxFrame.h"
 
 #include "nsReadableUtils.h"
 #include "nsCOMPtr.h"
@@ -505,35 +505,34 @@ nsTextBoxFrame::DrawText(nsRenderingCont
 
     aRenderingContext.SetColor(aOverrideColor ? *aOverrideColor : StyleColor()->mColor);
 
 #ifdef IBMBIDI
     nsresult rv = NS_ERROR_FAILURE;
 
     if (mState & NS_FRAME_IS_BIDI) {
       presContext->SetBidiEnabled();
-      const nsStyleVisibility* vis = StyleVisibility();
-      nsBidiDirection direction = (NS_STYLE_DIRECTION_RTL == vis->mDirection) ? NSBIDI_RTL : NSBIDI_LTR;
+      nsBidiLevel level = nsBidiPresUtils::BidiLevelFromStyle(StyleContext());
       if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
           // We let the RenderText function calculate the mnemonic's
           // underline position for us.
           nsBidiPositionResolve posResolve;
           posResolve.logicalIndex = mAccessKeyInfo->mAccesskeyIndex;
-          rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction,
+          rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), level,
                                            presContext, aRenderingContext,
                                            *refContext,
                                            aTextRect.x, baseline,
                                            &posResolve,
                                            1);
           mAccessKeyInfo->mBeforeWidth = posResolve.visualLeftTwips;
           mAccessKeyInfo->mAccessWidth = posResolve.visualWidth;
       }
       else
       {
-          rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction,
+          rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), level,
                                            presContext, aRenderingContext,
                                            *refContext,
                                            aTextRect.x, baseline);
       }
     }
     if (NS_FAILED(rv) )
 #endif // IBMBIDI
     {
--- a/layout/xul/tree/nsTreeBodyFrame.cpp
+++ b/layout/xul/tree/nsTreeBodyFrame.cpp
@@ -3270,37 +3270,34 @@ nsTreeBodyFrame::PaintCell(int32_t      
 
   // Now paint our element, but only if we aren't a cycler column.
   // XXX until we have the ability to load images, allow the view to 
   // insert text into cycler columns...
   if (!aColumn->IsCycler()) {
     nsRect elementRect(currX, cellRect.y, remainingWidth, cellRect.height);
     nsRect dirtyRect;
     if (dirtyRect.IntersectRect(aDirtyRect, elementRect)) {
-      bool textRTL = cellContext->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
       switch (aColumn->GetType()) {
         case nsITreeColumn::TYPE_TEXT:
-          PaintText(aRowIndex, aColumn, elementRect, aPresContext, aRenderingContext, aDirtyRect, currX,
-                    textRTL);
+          PaintText(aRowIndex, aColumn, elementRect, aPresContext, aRenderingContext, aDirtyRect, currX);
           break;
         case nsITreeColumn::TYPE_CHECKBOX:
           PaintCheckbox(aRowIndex, aColumn, elementRect, aPresContext, aRenderingContext, aDirtyRect);
           break;
         case nsITreeColumn::TYPE_PROGRESSMETER:
           int32_t state;
           mView->GetProgressMode(aRowIndex, aColumn, &state);
           switch (state) {
             case nsITreeView::PROGRESS_NORMAL:
             case nsITreeView::PROGRESS_UNDETERMINED:
               PaintProgressMeter(aRowIndex, aColumn, elementRect, aPresContext, aRenderingContext, aDirtyRect);
               break;
             case nsITreeView::PROGRESS_NONE:
             default:
-              PaintText(aRowIndex, aColumn, elementRect, aPresContext, aRenderingContext, aDirtyRect, currX,
-                        textRTL);
+              PaintText(aRowIndex, aColumn, elementRect, aPresContext, aRenderingContext, aDirtyRect, currX);
               break;
           }
           break;
       }
     }
   }
 
   aCurrX = currX;
@@ -3550,18 +3547,17 @@ nsTreeBodyFrame::PaintImage(int32_t     
 
 void
 nsTreeBodyFrame::PaintText(int32_t              aRowIndex,
                            nsTreeColumn*        aColumn,
                            const nsRect&        aTextRect,
                            nsPresContext*      aPresContext,
                            nsRenderingContext& aRenderingContext,
                            const nsRect&        aDirtyRect,
-                           nscoord&             aCurrX,
-                           bool                 aTextRTL)
+                           nscoord&             aCurrX)
 {
   NS_PRECONDITION(aColumn && aColumn->GetFrame(), "invalid column passed");
 
   bool isRTL = StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL;
 
   // Now obtain the text for our cell.
   nsAutoString text;
   mView->GetCellText(aRowIndex, aColumn, text);
@@ -3634,26 +3630,25 @@ nsTreeBodyFrame::PaintText(int32_t      
       aRenderingContext.FillRect(textRect.x, textRect.y, textRect.width, size);
     if (decorations & NS_FONT_DECORATION_UNDERLINE)
       aRenderingContext.FillRect(textRect.x, textRect.y + baseline - offset, textRect.width, size);
   }
   if (decorations & NS_FONT_DECORATION_LINE_THROUGH) {
     fontMet->GetStrikeout(offset, size);
     aRenderingContext.FillRect(textRect.x, textRect.y + baseline - offset, textRect.width, size);
   }
-  uint8_t direction = aTextRTL ? NS_STYLE_DIRECTION_RTL :
-                                 NS_STYLE_DIRECTION_LTR;
+  nsStyleContext* cellContext = GetPseudoStyleContext(nsCSSAnonBoxes::moztreecell);
 
   gfxContext* ctx = aRenderingContext.ThebesContext();
   if (opacity != 1.0f) {
     ctx->PushGroup(GFX_CONTENT_COLOR_ALPHA);
   }
 
   nsLayoutUtils::DrawString(this, &aRenderingContext, text.get(), text.Length(),
-                            textRect.TopLeft() + nsPoint(0, baseline), direction);
+                            textRect.TopLeft() + nsPoint(0, baseline), cellContext);
 
   if (opacity != 1.0f) {
     ctx->PopGroupToSource();
     ctx->Paint(opacity);
   }
 
 }
 
--- a/layout/xul/tree/nsTreeBodyFrame.h
+++ b/layout/xul/tree/nsTreeBodyFrame.h
@@ -243,18 +243,17 @@ protected:
 
   // This method paints the text string inside a particular cell of the tree.
   void PaintText(int32_t              aRowIndex, 
                  nsTreeColumn*        aColumn,
                  const nsRect&        aTextRect,
                  nsPresContext*      aPresContext,
                  nsRenderingContext& aRenderingContext,
                  const nsRect&        aDirtyRect,
-                 nscoord&             aCurrX,
-                 bool                 aTextRTL);
+                 nscoord&             aCurrX);
 
   // This method paints the checkbox inside a particular cell of the tree.
   void PaintCheckbox(int32_t              aRowIndex, 
                      nsTreeColumn*        aColumn,
                      const nsRect&        aCheckboxRect,
                      nsPresContext*      aPresContext,
                      nsRenderingContext& aRenderingContext,
                      const nsRect&        aDirtyRect);