Attachment #519654: Patch for bug #624798

View | Details | Raw Unified | Return to bug 624798
Collapse All | Expand All

(-)a/content/canvas/src/nsCanvasRenderingContext2D.cpp (-31 / +32 lines)
Line     Link Here 
 Lines 109-124    Link Here 
109
#include "gfxTextRunCache.h"
109
#include "gfxTextRunCache.h"
110
#include "gfxBlur.h"
110
#include "gfxBlur.h"
111
#include "gfxUtils.h"
111
#include "gfxUtils.h"
112
112
113
#include "nsFrameManager.h"
113
#include "nsFrameManager.h"
114
114
115
#include "nsFrameLoader.h"
115
#include "nsFrameLoader.h"
116
116
117
#include "nsBidi.h"
117
#include "nsBidiPresUtils.h"
118
#include "nsBidiPresUtils.h"
118
119
119
#include "Layers.h"
120
#include "Layers.h"
120
121
121
#include "CanvasUtils.h"
122
#include "CanvasUtils.h"
122
123
123
#include "nsIMemoryReporter.h"
124
#include "nsIMemoryReporter.h"
124
125
 Lines 2629-2648   nsCanvasRenderingContext2D::DrawOrMeasur Link Here 
2629
    }
2630
    }
2630
2631
2631
    nsIPresShell* presShell = GetPresShell();
2632
    nsIPresShell* presShell = GetPresShell();
2632
    if (!presShell)
2633
    if (!presShell)
2633
        return NS_ERROR_FAILURE;
2634
        return NS_ERROR_FAILURE;
2634
2635
2635
    nsIDocument* document = presShell->GetDocument();
2636
    nsIDocument* document = presShell->GetDocument();
2636
2637
2637
    nsBidiPresUtils* bidiUtils = presShell->GetPresContext()->GetBidiUtils();
2638
    if (!bidiUtils)
2639
        return NS_ERROR_FAILURE;
2640
2641
    // replace all the whitespace characters with U+0020 SPACE
2638
    // replace all the whitespace characters with U+0020 SPACE
2642
    nsAutoString textToDraw(aRawText);
2639
    nsAutoString textToDraw(aRawText);
2643
    TextReplaceWhitespaceCharacters(textToDraw);
2640
    TextReplaceWhitespaceCharacters(textToDraw);
2644
2641
2645
    // for now, default to ltr if not in doc
2642
    // for now, default to ltr if not in doc
2646
    PRBool isRTL = PR_FALSE;
2643
    PRBool isRTL = PR_FALSE;
2647
2644
2648
    if (content && content->IsInDoc()) {
2645
    if (content && content->IsInDoc()) {
 Lines 2678-2702   nsCanvasRenderingContext2D::DrawOrMeasur Link Here 
2678
2675
2679
    processor.mFontgrp = GetCurrentFontStyle();
2676
    processor.mFontgrp = GetCurrentFontStyle();
2680
    NS_ASSERTION(processor.mFontgrp, "font group is null");
2677
    NS_ASSERTION(processor.mFontgrp, "font group is null");
2681
2678
2682
    nscoord totalWidth;
2679
    nscoord totalWidth;
2683
2680
2684
    // calls bidi algo twice since it needs the full text width and the
2681
    // calls bidi algo twice since it needs the full text width and the
2685
    // bounding boxes before rendering anything
2682
    // bounding boxes before rendering anything
2686
    rv = bidiUtils->ProcessText(textToDraw.get(),
2683
    nsBidi bidiEngine;
2687
                                textToDraw.Length(),
2684
    rv = nsBidiPresUtils::ProcessText(textToDraw.get(),
2688
                                isRTL ? NSBIDI_RTL : NSBIDI_LTR,
2685
                                      textToDraw.Length(),
2689
                                presShell->GetPresContext(),
2686
                                      isRTL ? NSBIDI_RTL : NSBIDI_LTR,
2690
                                processor,
2687
                                      presShell->GetPresContext(),
2691
                                nsBidiPresUtils::MODE_MEASURE,
2688
                                      processor,
2692
                                nsnull,
2689
                                      nsBidiPresUtils::MODE_MEASURE,
2693
                                0,
2690
                                      nsnull,
2694
                                &totalWidth);
2691
                                      0,
2692
                                      &totalWidth,
2693
                                      &bidiEngine);
2695
    if (NS_FAILED(rv))
2694
    if (NS_FAILED(rv))
2696
        return rv;
2695
        return rv;
2697
2696
2698
    if (aWidth)
2697
    if (aWidth)
2699
        *aWidth = static_cast<float>(totalWidth);
2698
        *aWidth = static_cast<float>(totalWidth);
2700
2699
2701
    // if only measuring, don't need to do any more work
2700
    // if only measuring, don't need to do any more work
2702
    if (aOp==TEXT_DRAW_OPERATION_MEASURE)
2701
    if (aOp==TEXT_DRAW_OPERATION_MEASURE)
 Lines 2785-2809   nsCanvasRenderingContext2D::DrawOrMeasur Link Here 
2785
2784
2786
        gfxContext* ctx = ShadowInitialize(drawExtents, blur);
2785
        gfxContext* ctx = ShadowInitialize(drawExtents, blur);
2787
2786
2788
        if (ctx) {
2787
        if (ctx) {
2789
            CopyContext(ctx, mThebes);
2788
            CopyContext(ctx, mThebes);
2790
            ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
2789
            ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
2791
            processor.mThebes = ctx;
2790
            processor.mThebes = ctx;
2792
2791
2793
            rv = bidiUtils->ProcessText(textToDraw.get(),
2792
            rv = nsBidiPresUtils::ProcessText(textToDraw.get(),
2794
                                        textToDraw.Length(),
2793
                                              textToDraw.Length(),
2795
                                        isRTL ? NSBIDI_RTL : NSBIDI_LTR,
2794
                                              isRTL ? NSBIDI_RTL : NSBIDI_LTR,
2796
                                        presShell->GetPresContext(),
2795
                                              presShell->GetPresContext(),
2797
                                        processor,
2796
                                              processor,
2798
                                        nsBidiPresUtils::MODE_DRAW,
2797
                                              nsBidiPresUtils::MODE_DRAW,
2799
                                        nsnull,
2798
                                              nsnull,
2800
                                        0,
2799
                                              0,
2801
                                        nsnull);
2800
                                              nsnull,
2801
                                              &bidiEngine);
2802
            if (NS_FAILED(rv))
2802
            if (NS_FAILED(rv))
2803
                return rv;
2803
                return rv;
2804
2804
2805
            ShadowFinalize(blur);
2805
            ShadowFinalize(blur);
2806
        }
2806
        }
2807
2807
2808
        processor.mThebes = mThebes;
2808
        processor.mThebes = mThebes;
2809
    }
2809
    }
 Lines 2822-2846   nsCanvasRenderingContext2D::DrawOrMeasur Link Here 
2822
2822
2823
            // don't want operators to be applied twice
2823
            // don't want operators to be applied twice
2824
            mThebes->SetOperator(gfxContext::OPERATOR_SOURCE);
2824
            mThebes->SetOperator(gfxContext::OPERATOR_SOURCE);
2825
        }
2825
        }
2826
2826
2827
        ApplyStyle(STYLE_FILL);
2827
        ApplyStyle(STYLE_FILL);
2828
    }
2828
    }
2829
2829
2830
    rv = bidiUtils->ProcessText(textToDraw.get(),
2830
    rv = nsBidiPresUtils::ProcessText(textToDraw.get(),
2831
                                textToDraw.Length(),
2831
                                      textToDraw.Length(),
2832
                                isRTL ? NSBIDI_RTL : NSBIDI_LTR,
2832
                                      isRTL ? NSBIDI_RTL : NSBIDI_LTR,
2833
                                presShell->GetPresContext(),
2833
                                      presShell->GetPresContext(),
2834
                                processor,
2834
                                      processor,
2835
                                nsBidiPresUtils::MODE_DRAW,
2835
                                      nsBidiPresUtils::MODE_DRAW,
2836
                                nsnull,
2836
                                      nsnull,
2837
                                0,
2837
                                      0,
2838
                                nsnull);
2838
                                      nsnull,
2839
                                      &bidiEngine);
2839
2840
2840
    // this needs to be restored before function can return
2841
    // this needs to be restored before function can return
2841
    if (doUseIntermediateSurface) {
2842
    if (doUseIntermediateSurface) {
2842
        mThebes->PopGroupToSource();
2843
        mThebes->PopGroupToSource();
2843
        DirtyAllStyles();
2844
        DirtyAllStyles();
2844
    }
2845
    }
2845
2846
2846
    if (NS_FAILED(rv))
2847
    if (NS_FAILED(rv))
(-)a/layout/base/nsBidi.h (-3 / +3 lines)
Line     Link Here 
 Lines 768-784   public: Link Here 
768
   *      the number of objects to be reordered.
768
   *      the number of objects to be reordered.
769
   *      It must be <code>aLength>0</code>.
769
   *      It must be <code>aLength>0</code>.
770
   *
770
   *
771
   * @param aIndexMap is a pointer to an array of <code>aLength</code>
771
   * @param aIndexMap is a pointer to an array of <code>aLength</code>
772
   *      indexes which will reflect the reordering of the characters.
772
   *      indexes which will reflect the reordering of the characters.
773
   *      The array does not need to be initialized.<p>
773
   *      The array does not need to be initialized.<p>
774
   *      The index map will result in <code>aIndexMap[aLogicalIndex]==aVisualIndex</code>.
774
   *      The index map will result in <code>aIndexMap[aLogicalIndex]==aVisualIndex</code>.
775
   */
775
   */
776
  nsresult ReorderLogical(const nsBidiLevel *aLevels, PRInt32 aLength, PRInt32 *aIndexMap);
776
  static nsresult ReorderLogical(const nsBidiLevel *aLevels, PRInt32 aLength, PRInt32 *aIndexMap);
777
#endif // FULL_BIDI_ENGINE
777
#endif // FULL_BIDI_ENGINE
778
  /**
778
  /**
779
   * This is a convenience function that does not use a nsBidi object.
779
   * This is a convenience function that does not use a nsBidi object.
780
   * It is intended to be used for when an application has determined the levels
780
   * It is intended to be used for when an application has determined the levels
781
   * of objects (character sequences) and just needs to have them reordered (L2).
781
   * of objects (character sequences) and just needs to have them reordered (L2).
782
   * This is equivalent to using <code>GetVisualMap</code> on a
782
   * This is equivalent to using <code>GetVisualMap</code> on a
783
   * <code>nsBidi</code> object.
783
   * <code>nsBidi</code> object.
784
   *
784
   *
 Lines 789-805   public: Link Here 
789
   *      the number of objects to be reordered.
789
   *      the number of objects to be reordered.
790
   *      It must be <code>aLength>0</code>.
790
   *      It must be <code>aLength>0</code>.
791
   *
791
   *
792
   * @param aIndexMap is a pointer to an array of <code>aLength</code>
792
   * @param aIndexMap is a pointer to an array of <code>aLength</code>
793
   *      indexes which will reflect the reordering of the characters.
793
   *      indexes which will reflect the reordering of the characters.
794
   *      The array does not need to be initialized.<p>
794
   *      The array does not need to be initialized.<p>
795
   *      The index map will result in <code>aIndexMap[aVisualIndex]==aLogicalIndex</code>.
795
   *      The index map will result in <code>aIndexMap[aVisualIndex]==aLogicalIndex</code>.
796
   */
796
   */
797
  nsresult ReorderVisual(const nsBidiLevel *aLevels, PRInt32 aLength, PRInt32 *aIndexMap);
797
  static nsresult ReorderVisual(const nsBidiLevel *aLevels, PRInt32 aLength, PRInt32 *aIndexMap);
798
798
799
#ifdef FULL_BIDI_ENGINE
799
#ifdef FULL_BIDI_ENGINE
800
  /**
800
  /**
801
   * Invert an index map.
801
   * Invert an index map.
802
   * The one-to-one index mapping of the first map is inverted and written to
802
   * The one-to-one index mapping of the first map is inverted and written to
803
   * the second one.
803
   * the second one.
804
   *
804
   *
805
   * @param aSrcMap is an array with <code>aLength</code> indexes
805
   * @param aSrcMap is an array with <code>aLength</code> indexes
 Lines 912-927   private: Link Here 
912
  void SetTrailingWSStart();
912
  void SetTrailingWSStart();
913
913
914
  PRBool GetRuns();
914
  PRBool GetRuns();
915
915
916
  void GetSingleRun(nsBidiLevel aLevel);
916
  void GetSingleRun(nsBidiLevel aLevel);
917
917
918
  void ReorderLine(nsBidiLevel aMinLevel, nsBidiLevel aMaxLevel);
918
  void ReorderLine(nsBidiLevel aMinLevel, nsBidiLevel aMaxLevel);
919
919
920
  PRBool PrepareReorder(const nsBidiLevel *aLevels, PRInt32 aLength, PRInt32 *aIndexMap, nsBidiLevel *aMinLevel, nsBidiLevel *aMaxLevel);
920
  static PRBool PrepareReorder(const nsBidiLevel *aLevels, PRInt32 aLength, PRInt32 *aIndexMap, nsBidiLevel *aMinLevel, nsBidiLevel *aMaxLevel);
921
921
922
  PRInt32 doWriteReverse(const PRUnichar *src, PRInt32 srcLength,
922
  PRInt32 doWriteReverse(const PRUnichar *src, PRInt32 srcLength,
923
                         PRUnichar *dest, PRUint16 options);
923
                         PRUnichar *dest, PRUint16 options);
924
924
925
};
925
};
926
926
927
#endif // _nsBidi_h_
927
#endif // _nsBidi_h_
(-)a/layout/base/nsBidiPresUtils.cpp (-356 / +317 lines)
Line     Link Here 
 Lines 69-112   static const PRUnichar kObjectSubstitute Link Here 
69
static const PRUnichar kLRE              = 0x202A;
69
static const PRUnichar kLRE              = 0x202A;
70
static const PRUnichar kRLE              = 0x202B;
70
static const PRUnichar kRLE              = 0x202B;
71
static const PRUnichar kLRO              = 0x202D;
71
static const PRUnichar kLRO              = 0x202D;
72
static const PRUnichar kRLO              = 0x202E;
72
static const PRUnichar kRLO              = 0x202E;
73
static const PRUnichar kPDF              = 0x202C;
73
static const PRUnichar kPDF              = 0x202C;
74
74
75
#define NS_BIDI_CONTROL_FRAME ((nsIFrame*)0xfffb1d1)
75
#define NS_BIDI_CONTROL_FRAME ((nsIFrame*)0xfffb1d1)
76
76
77
nsBidiPresUtils::nsBidiPresUtils() : mArraySize(8),
77
struct BidiParagraphData {
78
                                     mIndexMap(nsnull),
78
  nsString            mBuffer;
79
                                     mLevels(nsnull),
79
  nsTArray<PRUnichar> mEmbeddingStack;
80
                                     mSuccess(NS_ERROR_FAILURE),
80
  nsTArray<nsIFrame*> mLogicalFrames;
81
                                     mBidiEngine(nsnull)
81
  nsDataHashtable<nsISupportsHashKey, PRInt32> mContentToFrameIndex;
82
{
82
  PRPackedBool        mIsVisual;
83
  mBidiEngine = new nsBidi();
83
  nsBidiLevel         mParaLevel;
84
  if (mBidiEngine && mContentToFrameIndex.Init()) {
84
  nsIContent*         mPrevContent;
85
    mSuccess = NS_OK;
85
  nsBidi*             mBidiEngine;
86
87
  void Init(nsBlockFrame *aBlockFrame)
88
  {
89
    mContentToFrameIndex.Init();
90
    mBidiEngine = new nsBidi();
91
    mPrevContent = nsnull;
92
    mParaLevel =
93
     (NS_STYLE_DIRECTION_RTL == aBlockFrame->GetStyleVisibility()->mDirection) ?
94
        NSBIDI_RTL : NSBIDI_LTR;
95
96
    mIsVisual = aBlockFrame->PresContext()->IsVisualMode();
97
    if (mIsVisual) {
98
      /**
99
       * Drill up in content to detect whether this is an element that needs to
100
       * be rendered with logical order even on visual pages.
101
       *
102
       * We always use logical order on form controls, firstly so that text
103
       * entry will be in logical order, but also because visual pages were
104
       * written with the assumption that even if the browser had no support
105
       * for right-to-left text rendering, it would use native widgets with
106
       * bidi support to display form controls.
107
       *
108
       * We also use logical order in XUL elements, since we expect that if a
109
       * XUL element appears in a visual page, it will be generated by an XBL
110
       * binding and contain localized text which will be in logical order.
111
       */
112
      for (nsIContent* content = aBlockFrame->GetContent() ; content; 
113
           content = content->GetParent()) {
114
        if (content->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) ||
115
            content->IsXUL()) {
116
          mIsVisual = PR_FALSE;
117
          break;
118
        }
119
      }
120
    }
86
  }
121
  }
87
}
88
122
89
nsBidiPresUtils::~nsBidiPresUtils()
123
  void Destroy() { delete mBidiEngine; }
90
{
124
91
  if (mLevels) {
125
  nsresult SetPara()
92
    delete[] mLevels;
126
  {
127
    return mBidiEngine->SetPara(mBuffer.get(), BufferLength(),
128
                                mParaLevel, nsnull);
93
  }
129
  }
94
  if (mIndexMap) {
130
95
    delete[] mIndexMap;
131
  nsresult CountRuns(PRInt32 *runCount){ return mBidiEngine->CountRuns(runCount); }
132
133
  nsresult GetLogicalRun(PRInt32 aLogicalStart, 
134
                         PRInt32* aLogicalLimit,
135
                         nsBidiLevel* aLevel)
136
  {
137
    nsresult rv = mBidiEngine->GetLogicalRun(aLogicalStart,
138
                                             aLogicalLimit, aLevel);
139
    if (mIsVisual || NS_FAILED(rv))
140
      *aLevel = mParaLevel;
141
    return rv;
96
  }
142
  }
97
  delete mBidiEngine;
98
}
99
143
100
PRBool
144
  void ResetData()
101
nsBidiPresUtils::IsSuccessful() const
145
  {
102
{ 
146
    mLogicalFrames.Clear();
103
  return NS_SUCCEEDED(mSuccess); 
147
    mContentToFrameIndex.Clear();
104
}
148
    mBuffer.SetLength(0);
149
    for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) {
150
      mBuffer.Append(mEmbeddingStack[i]);
151
      mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
152
    }
153
  }
154
155
  void AppendFrame(nsIFrame* aFrame, nsIContent* aContent = nsnull)
156
  {
157
    if (aContent) {
158
      mContentToFrameIndex.Put(aContent, FrameCount());
159
    }
160
    mLogicalFrames.AppendElement(aFrame);
161
  }
162
163
  PRInt32 GetLastFrameForContent(nsIContent *aContent)
164
  {
165
    PRInt32 index = 0;
166
    mContentToFrameIndex.Get(aContent, &index);
167
    return index;
168
  }
169
170
  PRInt32 FrameCount(){ return mLogicalFrames.Length(); }
171
172
  PRInt32 BufferLength(){ return mBuffer.Length(); }
173
174
  nsIFrame* FrameAt(PRInt32 aIndex){ return mLogicalFrames[aIndex]; }
175
176
  void AppendUnichar(PRUnichar aCh){ mBuffer.Append(aCh); }
177
178
  void AppendString(const nsDependentSubstring& aString){ mBuffer.Append(aString); }
179
180
  void PushBidiControl(PRUnichar aCh)
181
  {
182
    mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
183
    mBuffer.Append(aCh);
184
    mEmbeddingStack.AppendElement(aCh);
185
  }
186
187
  void PopBidiControl()
188
  {
189
    mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
190
    mBuffer.Append(kPDF);
191
    NS_ASSERTION(mEmbeddingStack.Length(), "embedding/override underflow");
192
    mEmbeddingStack.TruncateLength(mEmbeddingStack.Length() - 1);
193
  }
194
195
  void ClearBidiControls()
196
  {
197
    for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) {
198
      mBuffer.Append(kPDF);
199
      mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
200
    }
201
  }
202
};
203
204
struct BidiLineData {
205
  nsTArray<nsIFrame*> mLogicalFrames;
206
  nsTArray<nsIFrame*> mVisualFrames;
207
  nsTArray<PRInt32>   mIndexMap;
208
  nsTArray<PRUint8>   mLevels;
209
  PRBool              mIsReordered;
210
211
  BidiLineData(nsIFrame* aFirstFrameOnLine, PRInt32   aNumFramesOnLine)
212
  {
213
    /**
214
     * Initialize the logically-ordered array of frames using the top-level
215
     * frames of a single line
216
     */
217
    mLogicalFrames.Clear();
218
219
    PRBool isReordered = PR_FALSE;
220
    PRBool hasRTLFrames = PR_FALSE;
221
222
    for (nsIFrame* frame = aFirstFrameOnLine;
223
         frame && aNumFramesOnLine--;
224
         frame = frame->GetNextSibling()) {
225
      AppendFrame(frame);
226
      PRUint8 level = nsBidiPresUtils::GetFrameEmbeddingLevel(frame);
227
      mLevels.AppendElement(level);
228
      mIndexMap.AppendElement(0);
229
      if (level & 1) {
230
        hasRTLFrames = PR_TRUE;
231
      }
232
    }
233
234
    // Reorder the line
235
    nsBidi::ReorderVisual(mLevels.Elements(), FrameCount(),
236
                          mIndexMap.Elements());
237
238
    for (PRInt32 i = 0; i < FrameCount(); i++) {
239
      mVisualFrames.AppendElement(LogicalFrameAt(mIndexMap[i]));
240
      if (i != mIndexMap[i]) {
241
        isReordered = PR_TRUE;
242
      }
243
    }
244
245
    // If there's an RTL frame, assume the line is reordered
246
    mIsReordered = isReordered || hasRTLFrames;
247
  }
248
249
  void AppendFrame(nsIFrame* aFrame){ mLogicalFrames.AppendElement(aFrame); }
250
251
  PRInt32 FrameCount(){ return mLogicalFrames.Length(); }
252
253
  nsIFrame* LogicalFrameAt(PRInt32 aIndex){ return mLogicalFrames[aIndex]; }
254
255
  nsIFrame* VisualFrameAt(PRInt32 aIndex){ return mVisualFrames[aIndex]; }
256
};
105
257
106
/* Some helper methods for Resolve() */
258
/* Some helper methods for Resolve() */
107
259
108
// Should this frame be split between text runs?
260
// Should this frame be split between text runs?
109
PRBool
261
PRBool
110
IsBidiSplittable(nsIFrame* aFrame) {
262
IsBidiSplittable(nsIFrame* aFrame) {
111
  nsIAtom* frameType = aFrame->GetType();
263
  nsIAtom* frameType = aFrame->GetType();
112
  // Bidi inline containers should be split, unless they're line frames.
264
  // Bidi inline containers should be split, unless they're line frames.
 Lines 318-529   AdvanceLineIteratorToFrame(nsIFrame* aFr Link Here 
318
 *  The rendering layer requires each text frame to contain text in only one
470
 *  The rendering layer requires each text frame to contain text in only one
319
 *  direction, so we may need to call EnsureBidiContinuation() to split frames.
471
 *  direction, so we may need to call EnsureBidiContinuation() to split frames.
320
 *  We may also need to call RemoveBidiContinuation() to convert frames created
472
 *  We may also need to call RemoveBidiContinuation() to convert frames created
321
 *  by EnsureBidiContinuation() in previous reflows into fluid continuations.
473
 *  by EnsureBidiContinuation() in previous reflows into fluid continuations.
322
 */
474
 */
323
nsresult
475
nsresult
324
nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
476
nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
325
{
477
{
326
  mLogicalFrames.Clear();
478
  BidiParagraphData bpd;
327
  mContentToFrameIndex.Clear();
479
  bpd.Init(aBlockFrame);
328
  mBuffer.SetLength(0);
329
  mEmbeddingStack.Clear();
330
  
331
  nsPresContext *presContext = aBlockFrame->PresContext();
332
333
  const nsStyleVisibility* vis = aBlockFrame->GetStyleVisibility();
334
335
  mParaLevel = (NS_STYLE_DIRECTION_RTL == vis->mDirection) ?
336
                NSBIDI_RTL : NSBIDI_LTR;
337
338
  mLineIter = new nsBlockInFlowLineIterator(aBlockFrame,
339
                                            aBlockFrame->begin_lines(),
340
                                            PR_FALSE);
341
  if (mLineIter->GetLine() == aBlockFrame->end_lines()) {
342
    // Advance to first valid line (might be in a next-continuation)
343
    mLineIter->Next();
344
  }
345
346
  mIsVisual = presContext->IsVisualMode();
347
  if (mIsVisual) {
348
    /**
349
     * Drill up in content to detect whether this is an element that needs to be
350
     * rendered with logical order even on visual pages.
351
     *
352
     * We always use logical order on form controls, firstly so that text entry
353
     * will be in logical order, but also because visual pages were written with
354
     * the assumption that even if the browser had no support for right-to-left
355
     * text rendering, it would use native widgets with bidi support to display
356
     * form controls.
357
     *
358
     * We also use logical order in XUL elements, since we expect that if a XUL
359
     * element appears in a visual page, it will be generated by an XBL binding
360
     * and contain localized text which will be in logical order.
361
     */
362
    for (nsIContent* content = aBlockFrame->GetContent() ; content; 
363
         content = content->GetParent()) {
364
      if (content->IsNodeOfType(nsINode::eHTML_FORM_CONTROL) ||
365
          content->IsXUL()) {
366
        mIsVisual = PR_FALSE;
367
        break;
368
      }
369
    }
370
  }
371
  mPrevFrame = nsnull;
372
480
373
  // handle bidi-override being set on the block itself before calling
481
  // handle bidi-override being set on the block itself before calling
374
  // TraverseFrames.
482
  // TraverseFrames.
375
  const nsStyleTextReset* text = aBlockFrame->GetStyleTextReset();
483
  const nsStyleTextReset* text = aBlockFrame->GetStyleTextReset();
376
  PRUnichar ch = 0;
484
  PRUnichar ch = 0;
377
  if (text->mUnicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) {
485
  if (text->mUnicodeBidi == NS_STYLE_UNICODE_BIDI_OVERRIDE) {
486
    const nsStyleVisibility* vis = aBlockFrame->GetStyleVisibility();
378
    if (NS_STYLE_DIRECTION_RTL == vis->mDirection) {
487
    if (NS_STYLE_DIRECTION_RTL == vis->mDirection) {
379
      ch = kRLO;
488
      ch = kRLO;
380
    }
489
    }
381
    else if (NS_STYLE_DIRECTION_LTR == vis->mDirection) {
490
    else if (NS_STYLE_DIRECTION_LTR == vis->mDirection) {
382
      ch = kLRO;
491
      ch = kLRO;
383
    }
492
    }
384
    if (ch != 0) {
493
    if (ch != 0) {
385
      mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
494
      bpd.PushBidiControl(ch);
386
      mBuffer.Append(ch);
387
      mEmbeddingStack.AppendElement(ch);
388
    }
495
    }
389
  }
496
  }
390
  mPrevContent = nsnull;
391
  for (nsBlockFrame* block = aBlockFrame; block;
497
  for (nsBlockFrame* block = aBlockFrame; block;
392
       block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
498
       block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
393
    block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
499
    block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
394
    TraverseFrames(aBlockFrame, block->GetFirstChild(nsnull));
500
    TraverseFrames(aBlockFrame, block->GetFirstChild(nsnull), &bpd);
395
  }
501
  }
396
502
397
  if (ch != 0) {
503
  if (ch != 0) {
398
    mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
504
    bpd.PopBidiControl();
399
    mBuffer.Append(kPDF);
400
    NS_ASSERTION(mEmbeddingStack.Length(), "embedding/override underflow");
401
    mEmbeddingStack.TruncateLength(mEmbeddingStack.Length() - 1);
402
  }
505
  }
403
506
404
  // Resolve final paragraph
507
  // Resolve final paragraph
405
  ResolveParagraph(aBlockFrame);
508
  nsresult rv = ResolveParagraph(aBlockFrame, &bpd);
406
  return mSuccess;
509
  bpd.Destroy();
510
  return rv;
407
}
511
}
408
512
409
void
513
nsresult
410
nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame)
514
nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame,
515
                                  BidiParagraphData* aBpd)
411
{
516
{
412
  nsPresContext *presContext = aBlockFrame->PresContext();
517
  nsPresContext *presContext = aBlockFrame->PresContext();
413
  PRInt32 bufferLength = mBuffer.Length();
414
518
415
  if (bufferLength < 1) {
519
  if (aBpd->BufferLength() < 1) {
416
    mSuccess = NS_OK;
520
    return NS_OK;
417
    return;
418
  }
521
  }
419
  mBuffer.ReplaceChar("\t\r\n", kSpace);
522
  aBpd->mBuffer.ReplaceChar("\t\r\n", kSpace);
420
523
421
  PRInt32 runCount;
524
  PRInt32 runCount;
422
  PRUint8 embeddingLevel = mParaLevel;
525
  PRUint8 embeddingLevel = aBpd->mParaLevel;
423
526
424
  mSuccess = mBidiEngine->SetPara(mBuffer.get(), bufferLength, mParaLevel, nsnull);
527
  nsresult rv = aBpd->SetPara();
425
  if (NS_FAILED(mSuccess) ) {
528
  NS_ENSURE_SUCCESS(rv, rv);
426
      return;
427
  }
428
529
429
  mSuccess = mBidiEngine->CountRuns(&runCount);
530
  rv = aBpd->CountRuns(&runCount);
430
  if (NS_FAILED(mSuccess) ) {
531
  NS_ENSURE_SUCCESS(rv, rv);
431
    return;
532
432
  }
433
  PRInt32     runLength      = 0;   // the length of the current run of text
533
  PRInt32     runLength      = 0;   // the length of the current run of text
434
  PRInt32     lineOffset     = 0;   // the start of the current run
534
  PRInt32     lineOffset     = 0;   // the start of the current run
435
  PRInt32     logicalLimit   = 0;   // the end of the current run + 1
535
  PRInt32     logicalLimit   = 0;   // the end of the current run + 1
436
  PRInt32     numRun         = -1;
536
  PRInt32     numRun         = -1;
437
  PRInt32     fragmentLength = 0;   // the length of the current text frame
537
  PRInt32     fragmentLength = 0;   // the length of the current text frame
438
  PRInt32     frameIndex     = -1;  // index to the frames in mLogicalFrames
538
  PRInt32     frameIndex     = -1;  // index to the frames in mLogicalFrames
439
  PRInt32     frameCount     = mLogicalFrames.Length();
539
  PRInt32     frameCount     = aBpd->FrameCount();
440
  PRInt32     contentOffset  = 0;   // offset of current frame in its content node
540
  PRInt32     contentOffset  = 0;   // offset of current frame in its content node
441
  PRBool      isTextFrame    = PR_FALSE;
541
  PRBool      isTextFrame    = PR_FALSE;
442
  nsIFrame*   frame = nsnull;
542
  nsIFrame*   frame = nsnull;
443
  nsIContent* content = nsnull;
543
  nsIContent* content = nsnull;
444
  PRInt32     contentTextLength;
544
  PRInt32     contentTextLength;
445
545
446
  FramePropertyTable *propTable = presContext->PropertyTable();
546
  FramePropertyTable *propTable = presContext->PropertyTable();
447
547
548
  
549
  nsBlockInFlowLineIterator lineIter(aBlockFrame,
550
                                     aBlockFrame->begin_lines(),
551
                                     PR_FALSE);
552
  if (lineIter.GetLine() == aBlockFrame->end_lines()) {
553
    // Advance to first valid line (might be in a next-continuation)
554
    lineIter.Next();
555
  }
556
  nsIFrame* prevFrame = nsnull;
557
448
  if (frameCount == 1 && runCount == 1) {
558
  if (frameCount == 1 && runCount == 1) {
449
    // Nothing more to do, just make sure that the frame has the right
559
    // Nothing more to do, just make sure that the frame has the right
450
    // embedding level.
560
    // embedding level.
451
    if (mIsVisual ||
561
    aBpd->GetLogicalRun(lineOffset, &logicalLimit, &embeddingLevel);
452
        NS_FAILED(mBidiEngine->GetLogicalRun(lineOffset, &logicalLimit,
453
                                             &embeddingLevel))) {
454
      embeddingLevel = mParaLevel;
455
    }
456
562
457
    frame = mLogicalFrames[0];
563
    frame = aBpd->FrameAt(0);
458
    nsBidiLevel oldEmbeddingLevel = NS_GET_EMBEDDING_LEVEL(frame);
564
    nsBidiLevel oldEmbeddingLevel = NS_GET_EMBEDDING_LEVEL(frame);
459
    nsBidiLevel oldBaseLevel = NS_GET_BASE_LEVEL(frame);
565
    nsBidiLevel oldBaseLevel = NS_GET_BASE_LEVEL(frame);
460
566
461
    if (oldEmbeddingLevel != embeddingLevel ||
567
    if (oldEmbeddingLevel != embeddingLevel ||
462
        oldBaseLevel != mParaLevel) {
568
        oldBaseLevel != aBpd->mParaLevel) {
463
      frame->Properties().Set(nsIFrame::EmbeddingLevelProperty(),
569
      frame->Properties().Set(nsIFrame::EmbeddingLevelProperty(),
464
                              NS_INT32_TO_PTR(embeddingLevel));
570
                              NS_INT32_TO_PTR(embeddingLevel));
465
      frame->Properties().Set(nsIFrame::BaseLevelProperty(),
571
      frame->Properties().Set(nsIFrame::BaseLevelProperty(),
466
                              NS_INT32_TO_PTR(mParaLevel));
572
                              NS_INT32_TO_PTR(aBpd->mParaLevel));
467
      AdvanceLineIteratorToFrame(frame, mLineIter, mPrevFrame);
573
      AdvanceLineIteratorToFrame(frame, &lineIter, prevFrame);
468
      mLineIter->GetLine()->MarkDirty();
574
      lineIter.GetLine()->MarkDirty();
469
      if (frame->GetType() == nsGkAtoms::textFrame) {
575
      if (frame->GetType() == nsGkAtoms::textFrame) {
470
        frame->AddStateBits(NS_FRAME_IS_BIDI);
576
        frame->AddStateBits(NS_FRAME_IS_BIDI);
471
      }
577
      }
472
    }
578
    }
473
579
474
    mSuccess = NS_OK;
580
    return NS_OK;
475
    return;
476
  }
581
  }
477
582
478
  PRBool lineNeedsUpdate = PR_FALSE;
583
  PRBool lineNeedsUpdate = PR_FALSE;
479
  
584
  
480
#ifdef NOISY_BIDI
585
#ifdef NOISY_BIDI
481
  if (mBuffer[0] != kObjectSubstitute) {
586
  if (aBpd->mBuffer[0] != kObjectSubstitute) {
482
    printf("Before Resolve(), aBlockFrame=0x%p, mBuffer='%s', frameCount=%d\n",
587
    printf("Before Resolve(), aBlockFrame=0x%p, mBuffer='%s', frameCount=%d\n",
483
           (void*)aBlockFrame, NS_ConvertUTF16toUTF8(mBuffer).get(), frameCount);
588
           (void*)aBlockFrame, NS_ConvertUTF16toUTF8(aBpd->mBuffer).get(), frameCount);
484
#ifdef REALLY_NOISY_BIDI
589
#ifdef REALLY_NOISY_BIDI
485
    printf(" frameTree=:\n");
590
    printf(" frameTree=:\n");
486
    nsFrame::DumpFrameTree(aBlockFrame);
591
    nsFrame::DumpFrameTree(aBlockFrame);
487
#endif
592
#endif
488
  }
593
  }
489
#endif
594
#endif
490
  for (; ;) {
595
  for (; ;) {
491
    if (fragmentLength <= 0) {
596
    if (fragmentLength <= 0) {
492
      // Get the next frame from mLogicalFrames
597
      // Get the next frame from mLogicalFrames
493
      if (++frameIndex >= frameCount) {
598
      if (++frameIndex >= frameCount) {
494
        break;
599
        break;
495
      }
600
      }
496
      frame = mLogicalFrames[frameIndex];
601
      frame = aBpd->FrameAt(frameIndex);
497
      lineNeedsUpdate = PR_TRUE;
602
      lineNeedsUpdate = PR_TRUE;
498
      if (frame == NS_BIDI_CONTROL_FRAME ||
603
      if (frame == NS_BIDI_CONTROL_FRAME ||
499
          nsGkAtoms::textFrame != frame->GetType()) {
604
          nsGkAtoms::textFrame != frame->GetType()) {
500
        /*
605
        /*
501
         * Any non-text frame corresponds to a single character in the text buffer
606
         * Any non-text frame corresponds to a single character in the text buffer
502
         * (a bidi control character, LINE SEPARATOR, or OBJECT SUBSTITUTE)
607
         * (a bidi control character, LINE SEPARATOR, or OBJECT SUBSTITUTE)
503
         */
608
         */
504
        isTextFrame = PR_FALSE;
609
        isTextFrame = PR_FALSE;
505
        fragmentLength = 1;
610
        fragmentLength = 1;
506
      }
611
      }
507
      else {
612
      else {
508
        content = frame->GetContent();
613
        content = frame->GetContent();
509
        if (!content) {
614
        if (!content) {
510
          mSuccess = NS_OK;
615
          rv = NS_OK;
511
          break;
616
          break;
512
        }
617
        }
513
        contentTextLength = content->TextLength();
618
        contentTextLength = content->TextLength();
514
        if (contentTextLength == 0) {
619
        if (contentTextLength == 0) {
515
          frame->AdjustOffsetsForBidi(0, 0);
620
          frame->AdjustOffsetsForBidi(0, 0);
516
          // Set the base level and embedding level of the current run even
621
          // Set the base level and embedding level of the current run even
517
          // on an empty frame. Otherwise frame reordering will not be correct.
622
          // on an empty frame. Otherwise frame reordering will not be correct.
518
          propTable->Set(frame, nsIFrame::EmbeddingLevelProperty(),
623
          propTable->Set(frame, nsIFrame::EmbeddingLevelProperty(),
519
                         NS_INT32_TO_PTR(embeddingLevel));
624
                         NS_INT32_TO_PTR(embeddingLevel));
520
          propTable->Set(frame, nsIFrame::BaseLevelProperty(),
625
          propTable->Set(frame, nsIFrame::BaseLevelProperty(),
521
                         NS_INT32_TO_PTR(mParaLevel));
626
                         NS_INT32_TO_PTR(aBpd->mParaLevel));
522
          continue;
627
          continue;
523
        }
628
        }
524
        PRInt32 start, end;
629
        PRInt32 start, end;
525
        frame->GetOffsets(start, end);
630
        frame->GetOffsets(start, end);
526
        NS_ASSERTION(!(contentTextLength < end - start),
631
        NS_ASSERTION(!(contentTextLength < end - start),
527
                     "Frame offsets don't fit in content");
632
                     "Frame offsets don't fit in content");
528
        fragmentLength = NS_MIN(contentTextLength, end - start);
633
        fragmentLength = NS_MIN(contentTextLength, end - start);
529
        contentOffset = start;
634
        contentOffset = start;
 Lines 532-636   nsBidiPresUtils::ResolveParagraph(nsBloc Link Here 
532
    } // if (fragmentLength <= 0)
637
    } // if (fragmentLength <= 0)
533
638
534
    if (runLength <= 0) {
639
    if (runLength <= 0) {
535
      // Get the next run of text from the Bidi engine
640
      // Get the next run of text from the Bidi engine
536
      if (++numRun >= runCount) {
641
      if (++numRun >= runCount) {
537
        break;
642
        break;
538
      }
643
      }
539
      lineOffset = logicalLimit;
644
      lineOffset = logicalLimit;
540
      if (NS_FAILED(mBidiEngine->GetLogicalRun(
645
      if (NS_FAILED(aBpd->GetLogicalRun(
541
              lineOffset, &logicalLimit, &embeddingLevel) ) ) {
646
              lineOffset, &logicalLimit, &embeddingLevel) ) ) {
542
        break;
647
        break;
543
      }
648
      }
544
      runLength = logicalLimit - lineOffset;
649
      runLength = logicalLimit - lineOffset;
545
      if (mIsVisual) {
546
        embeddingLevel = mParaLevel;
547
      }
548
    } // if (runLength <= 0)
650
    } // if (runLength <= 0)
549
651
550
    if (frame == NS_BIDI_CONTROL_FRAME) {
652
    if (frame == NS_BIDI_CONTROL_FRAME) {
551
      frame = nsnull;
653
      frame = nsnull;
552
      ++lineOffset;
654
      ++lineOffset;
553
    }
655
    }
554
    else {
656
    else {
555
      propTable->Set(frame, nsIFrame::EmbeddingLevelProperty(),
657
      propTable->Set(frame, nsIFrame::EmbeddingLevelProperty(),
556
                     NS_INT32_TO_PTR(embeddingLevel));
658
                     NS_INT32_TO_PTR(embeddingLevel));
557
      propTable->Set(frame, nsIFrame::BaseLevelProperty(),
659
      propTable->Set(frame, nsIFrame::BaseLevelProperty(),
558
                     NS_INT32_TO_PTR(mParaLevel));
660
                     NS_INT32_TO_PTR(aBpd->mParaLevel));
559
      if (isTextFrame) {
661
      if (isTextFrame) {
560
        if ( (runLength > 0) && (runLength < fragmentLength) ) {
662
        if ( (runLength > 0) && (runLength < fragmentLength) ) {
561
          /*
663
          /*
562
           * The text in this frame continues beyond the end of this directional run.
664
           * The text in this frame continues beyond the end of this directional run.
563
           * Create a non-fluid continuation frame for the next directional run.
665
           * Create a non-fluid continuation frame for the next directional run.
564
           */
666
           */
565
          if (lineNeedsUpdate) {
667
          if (lineNeedsUpdate) {
566
            AdvanceLineIteratorToFrame(frame, mLineIter, mPrevFrame);
668
            AdvanceLineIteratorToFrame(frame, &lineIter, prevFrame);
567
            lineNeedsUpdate = PR_FALSE;
669
            lineNeedsUpdate = PR_FALSE;
568
          }
670
          }
569
          mLineIter->GetLine()->MarkDirty();
671
          lineIter.GetLine()->MarkDirty();
570
          nsIFrame* nextBidi;
672
          nsIFrame* nextBidi;
571
          PRInt32 runEnd = contentOffset + runLength;
673
          PRInt32 runEnd = contentOffset + runLength;
572
          EnsureBidiContinuation(frame, &nextBidi, frameIndex,
674
          rv = EnsureBidiContinuation(frame, &nextBidi, frameIndex,
573
                                 contentOffset,
675
                                      contentOffset,
574
                                 runEnd);
676
                                      runEnd);
575
          if (NS_FAILED(mSuccess)) {
677
          if (NS_FAILED(rv)) {
576
            break;
678
            break;
577
          }
679
          }
578
          nextBidi->AdjustOffsetsForBidi(runEnd,
680
          nextBidi->AdjustOffsetsForBidi(runEnd,
579
                                         contentOffset + fragmentLength);
681
                                         contentOffset + fragmentLength);
580
          frame = nextBidi;
682
          frame = nextBidi;
581
          contentOffset = runEnd;
683
          contentOffset = runEnd;
582
        } // if (runLength < fragmentLength)
684
        } // if (runLength < fragmentLength)
583
        else {
685
        else {
584
          if (contentOffset + fragmentLength == contentTextLength) {
686
          if (contentOffset + fragmentLength == contentTextLength) {
585
            /* 
687
            /* 
586
             * We have finished all the text in this content node. Convert any
688
             * We have finished all the text in this content node. Convert any
587
             * further non-fluid continuations to fluid continuations and advance
689
             * further non-fluid continuations to fluid continuations and advance
588
             * frameIndex to the last frame in the content node
690
             * frameIndex to the last frame in the content node
589
             */
691
             */
590
            PRInt32 newIndex = 0;
692
            PRInt32 newIndex = aBpd->GetLastFrameForContent(content);
591
            mContentToFrameIndex.Get(content, &newIndex);
592
            if (newIndex > frameIndex) {
693
            if (newIndex > frameIndex) {
593
              RemoveBidiContinuation(frame, frameIndex, newIndex, lineOffset);
694
              RemoveBidiContinuation(aBpd, frame, 
695
                                     frameIndex, newIndex, lineOffset);
594
              frameIndex = newIndex;
696
              frameIndex = newIndex;
595
            }
697
            }
596
          } else if (fragmentLength > 0 && runLength > fragmentLength) {
698
          } else if (fragmentLength > 0 && runLength > fragmentLength) {
597
            /*
699
            /*
598
             * There is more text that belongs to this directional run in the next
700
             * There is more text that belongs to this directional run in the next
599
             * text frame: make sure it is a fluid continuation of the current frame.
701
             * text frame: make sure it is a fluid continuation of the current frame.
600
             * Do not advance frameIndex, because the next frame may contain
702
             * Do not advance frameIndex, because the next frame may contain
601
             * multi-directional text and need to be split
703
             * multi-directional text and need to be split
602
             */
704
             */
603
            PRInt32 newIndex = frameIndex;
705
            PRInt32 newIndex = frameIndex;
604
            do {
706
            do {
605
            } while (++newIndex < frameCount &&
707
            } while (++newIndex < frameCount &&
606
                     mLogicalFrames[newIndex] == NS_BIDI_CONTROL_FRAME);
708
                     aBpd->FrameAt(newIndex) == NS_BIDI_CONTROL_FRAME);
607
            if (newIndex < frameCount) {
709
            if (newIndex < frameCount) {
608
              RemoveBidiContinuation(frame, frameIndex, newIndex, lineOffset);
710
              RemoveBidiContinuation(aBpd, frame, 
711
                                     frameIndex, newIndex, lineOffset);
609
            }
712
            }
610
          } else if (runLength == fragmentLength &&
713
          } else if (runLength == fragmentLength &&
611
                     numRun + 1 < runCount) {
714
                     numRun + 1 < runCount) {
612
            /*
715
            /*
613
             * If the directional run ends at the end of the frame, and this is
716
             * If the directional run ends at the end of the frame, and this is
614
             * not the end of our paragraph, make sure that the next frame is a
717
             * not the end of our paragraph, make sure that the next frame is a
615
             * non-fluid continuation
718
             * non-fluid continuation
616
             */
719
             */
617
            nsIFrame* next = frame->GetNextInFlow();
720
            nsIFrame* next = frame->GetNextInFlow();
618
            if (next) {
721
            if (next) {
619
              frame->SetNextContinuation(next);
722
              frame->SetNextContinuation(next);
620
              next->SetPrevContinuation(frame);
723
              next->SetPrevContinuation(frame);
621
            }
724
            }
622
          }
725
          }
623
          frame->AdjustOffsetsForBidi(contentOffset, contentOffset + fragmentLength);
726
          frame->AdjustOffsetsForBidi(contentOffset, contentOffset + fragmentLength);
624
          if (lineNeedsUpdate) {
727
          if (lineNeedsUpdate) {
625
            AdvanceLineIteratorToFrame(frame, mLineIter, mPrevFrame);
728
            AdvanceLineIteratorToFrame(frame, &lineIter, prevFrame);
626
            lineNeedsUpdate = PR_FALSE;
729
            lineNeedsUpdate = PR_FALSE;
627
          }
730
          }
628
          mLineIter->GetLine()->MarkDirty();
731
          lineIter.GetLine()->MarkDirty();
629
        }
732
        }
630
      } // isTextFrame
733
      } // isTextFrame
631
      else {
734
      else {
632
        ++lineOffset;
735
        ++lineOffset;
633
      }
736
      }
634
    } // not bidi control frame
737
    } // not bidi control frame
635
    PRInt32 temp = runLength;
738
    PRInt32 temp = runLength;
636
    runLength -= fragmentLength;
739
    runLength -= fragmentLength;
 Lines 669-702   nsBidiPresUtils::ResolveParagraph(nsBloc Link Here 
669
        // We're not at an end of a run. If |frame| is the last child of its
772
        // We're not at an end of a run. If |frame| is the last child of its
670
        // parent, and its ancestors happen to have bidi continuations, convert
773
        // parent, and its ancestors happen to have bidi continuations, convert
671
        // them into fluid continuations.
774
        // them into fluid continuations.
672
        JoinInlineAncestors(frame);
775
        JoinInlineAncestors(frame);
673
      }
776
      }
674
    }
777
    }
675
  } // for
778
  } // for
676
#ifdef REALLY_NOISY_BIDI
779
#ifdef REALLY_NOISY_BIDI
677
  if (mBuffer[0] != kObjectSubstitute) {
780
  if (aBpd->mBuffer[0] != kObjectSubstitute) {
678
    printf("---\nAfter Resolve(), frameTree =:\n");
781
    printf("---\nAfter Resolve(), frameTree =:\n");
679
    nsFrame::DumpFrameTree(aBlockFrame);
782
    nsFrame::DumpFrameTree(aBlockFrame);
680
    printf("===\n");
783
    printf("===\n");
681
  }
784
  }
682
#endif
785
#endif
786
  return rv;
683
}
787
}
684
788
685
// Should this frame be treated as a leaf (e.g. when building mLogicalFrames)?
789
// Should this frame be treated as a leaf (e.g. when building mLogicalFrames)?
686
PRBool IsBidiLeaf(nsIFrame* aFrame) {
790
PRBool IsBidiLeaf(nsIFrame* aFrame) {
687
  nsIFrame* kid = aFrame->GetFirstChild(nsnull);
791
  nsIFrame* kid = aFrame->GetFirstChild(nsnull);
688
  return !kid
792
  return !kid
689
    || !aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer);
793
    || !aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer);
690
}
794
}
691
795
692
void
796
void
693
nsBidiPresUtils::TraverseFrames(nsBlockFrame* aBlockFrame,
797
nsBidiPresUtils::TraverseFrames(nsBlockFrame*      aBlockFrame,
694
                                nsIFrame*     aCurrentFrame)
798
                                nsIFrame*          aCurrentFrame,
799
                                BidiParagraphData* aBpd)
695
{
800
{
696
  if (!aCurrentFrame)
801
  if (!aCurrentFrame)
697
    return;
802
    return;
698
803
699
  nsIFrame* childFrame = aCurrentFrame;
804
  nsIFrame* childFrame = aCurrentFrame;
700
  do {
805
  do {
701
    /*
806
    /*
702
     * It's important to get the next sibling and next continuation *before*
807
     * It's important to get the next sibling and next continuation *before*
 Lines 744-784   nsBidiPresUtils::TraverseFrames(nsBlockF Link Here 
744
            ch = kLRO;
849
            ch = kLRO;
745
          }
850
          }
746
          break;
851
          break;
747
      }
852
      }
748
853
749
      // Add a dummy frame pointer representing a bidi control code before the
854
      // Add a dummy frame pointer representing a bidi control code before the
750
      // first frame of an element specifying embedding or override
855
      // first frame of an element specifying embedding or override
751
      if (ch != 0 && !frame->GetPrevContinuation()) {
856
      if (ch != 0 && !frame->GetPrevContinuation()) {
752
        mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
857
        aBpd->PushBidiControl(ch);
753
        mBuffer.Append(ch);
754
        mEmbeddingStack.AppendElement(ch);
755
      }
858
      }
756
    }
859
    }
757
860
758
    if (IsBidiLeaf(frame)) {
861
    if (IsBidiLeaf(frame)) {
759
      /* Bidi leaf frame: add the frame to the mLogicalFrames array,
862
      /* Bidi leaf frame: add the frame to the mLogicalFrames array,
760
       * and add its index to the mContentToFrameIndex hashtable. This
863
       * and add its index to the mContentToFrameIndex hashtable. This
761
       * will be used in RemoveBidiContinuation() to identify the last
864
       * will be used in RemoveBidiContinuation() to identify the last
762
       * frame in the array with a given content.
865
       * frame in the array with a given content.
763
       */
866
       */
764
      nsIContent* content = frame->GetContent();
867
      nsIContent* content = frame->GetContent();
765
      if (content) {
868
      aBpd->AppendFrame(frame, content);
766
        mContentToFrameIndex.Put(content, mLogicalFrames.Length());
767
      }
768
      mLogicalFrames.AppendElement(frame);
769
869
770
      // Append the content of the frame to the paragraph buffer
870
      // Append the content of the frame to the paragraph buffer
771
      nsIAtom* frameType = frame->GetType();
871
      nsIAtom* frameType = frame->GetType();
772
      if (nsGkAtoms::textFrame == frameType) {
872
      if (nsGkAtoms::textFrame == frameType) {
773
        if (content != mPrevContent) {
873
        if (content != aBpd->mPrevContent) {
774
          mPrevContent = content;
874
          aBpd->mPrevContent = content;
775
          if (!frame->GetStyleContext()->GetStyleText()->NewlineIsSignificant()) {
875
          if (!frame->GetStyleContext()->GetStyleText()->NewlineIsSignificant()) {
776
            content->AppendTextTo(mBuffer);
876
            content->AppendTextTo(aBpd->mBuffer);
777
          } else {
877
          } else {
778
            /*
878
            /*
779
             * For preformatted text we have to do bidi resolution on each line
879
             * For preformatted text we have to do bidi resolution on each line
780
             * separately. 
880
             * separately. 
781
             */
881
             */
782
            nsAutoString text;
882
            nsAutoString text;
783
            content->AppendTextTo(text);
883
            content->AppendTextTo(text);
784
            nsIFrame* next;
884
            nsIFrame* next;
 Lines 789-836   nsBidiPresUtils::TraverseFrames(nsBlockF Link Here 
789
              frame->GetOffsets(start, end);
889
              frame->GetOffsets(start, end);
790
              PRInt32 endLine = text.FindCharInSet(NS_LITERAL_STRING("\n\r"),
890
              PRInt32 endLine = text.FindCharInSet(NS_LITERAL_STRING("\n\r"),
791
                                                   start);
891
                                                   start);
792
              if (endLine == -1) {
892
              if (endLine == -1) {
793
                /*
893
                /*
794
                 * If there is no newline in the frame, just save the text and
894
                 * If there is no newline in the frame, just save the text and
795
                 * do bidi resolution later
895
                 * do bidi resolution later
796
                 */
896
                 */
797
                mBuffer.Append(Substring(text, start));
897
                aBpd->AppendString(Substring(text, start));
798
                break;
898
                break;
799
              }
899
              }
800
900
801
              /*
901
              /*
802
               * If there is a newline in the frame, break the frame after the
902
               * If there is a newline in the frame, break the frame after the
803
               * newline, do bidi resolution and repeat until the end of the
903
               * newline, do bidi resolution and repeat until the end of the
804
               * element.
904
               * element.
805
               */
905
               */
806
              ++endLine;
906
              ++endLine;
807
907
808
              /*
908
              /*
809
               * If the frame ends before the new line, save the text and move
909
               * If the frame ends before the new line, save the text and move
810
               * into the next continuation
910
               * into the next continuation
811
               */
911
               */
812
              while (end < endLine) {
912
              while (end < endLine) {
813
                mBuffer.Append(Substring(text, start, end - start));
913
                aBpd->AppendString(Substring(text, start, end - start));
814
                frame = frame->GetNextContinuation();
914
                frame = frame->GetNextContinuation();
815
                NS_ASSERTION(frame, "Premature end of continuation chain");
915
                NS_ASSERTION(frame, "Premature end of continuation chain");
816
                frame->GetOffsets(start, end);
916
                frame->GetOffsets(start, end);
817
                mLogicalFrames.AppendElement(frame);
917
                aBpd->AppendFrame(frame);
818
918
819
                /*
919
                /*
820
                 * If we have already overshot the saved next-sibling while
920
                 * If we have already overshot the saved next-sibling while
821
                 * scanning the frame's continuations, advance it.
921
                 * scanning the frame's continuations, advance it.
822
                 */
922
                 */
823
                if (frame == nextSibling) {
923
                if (frame == nextSibling) {
824
                  nextSibling = frame->GetNextSibling();
924
                  nextSibling = frame->GetNextSibling();
825
                }
925
                }
826
              }
926
              }
827
927
828
              mBuffer.Append(Substring(text, start, endLine - start));
928
              aBpd->AppendString(Substring(text, start, endLine - start));
829
929
830
              if (PRUint32(endLine) < text.Length()) {
930
              if (PRUint32(endLine) < text.Length()) {
831
                nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
931
                nsTextFrame* textFrame = static_cast<nsTextFrame*>(frame);
832
                textFrame->SetLength(endLine - start, nsnull);
932
                textFrame->SetLength(endLine - start, nsnull);
833
                next = frame->GetNextInFlow();
933
                next = frame->GetNextInFlow();
834
                if (!next) {
934
                if (!next) {
835
                  // If the frame already has a bidi continuation, make it fluid
935
                  // If the frame already has a bidi continuation, make it fluid
836
                  next = frame->GetNextContinuation();
936
                  next = frame->GetNextContinuation();
 Lines 838-1022   nsBidiPresUtils::TraverseFrames(nsBlockF Link Here 
838
                    MakeContinuationFluid(frame, next);
938
                    MakeContinuationFluid(frame, next);
839
                    JoinInlineAncestors(frame);
939
                    JoinInlineAncestors(frame);
840
                  } else {
940
                  } else {
841
                    // If the frame has no next in flow, create one
941
                    // If the frame has no next in flow, create one
842
                    CreateContinuation(frame, &next, PR_TRUE);
942
                    CreateContinuation(frame, &next, PR_TRUE);
843
                  }
943
                  }
844
                }
944
                }
845
              }
945
              }
846
              ResolveParagraphWithinBlock(aBlockFrame);
946
              ResolveParagraphWithinBlock(aBlockFrame, aBpd);
847
947
848
              if (next) {
948
              if (next) {
849
                frame = next;
949
                frame = next;
850
                mLogicalFrames.AppendElement(frame);
950
                aBpd->AppendFrame(frame);
851
              }
951
              }
852
952
853
              /*
953
              /*
854
               * If we have already overshot the saved next-sibling while
954
               * If we have already overshot the saved next-sibling while
855
               * scanning the frame's continuations, advance it.
955
               * scanning the frame's continuations, advance it.
856
               */
956
               */
857
              if (frame && frame == nextSibling) {
957
              if (frame && frame == nextSibling) {
858
                nextSibling = frame->GetNextSibling();
958
                nextSibling = frame->GetNextSibling();
859
              }
959
              }
860
960
861
            } while (next);
961
            } while (next);
862
          }
962
          }
863
        }
963
        }
864
      } else if (nsGkAtoms::brFrame == frameType) {
964
      } else if (nsGkAtoms::brFrame == frameType) {
865
        // break frame -- append line separator
965
        // break frame -- append line separator
866
        mBuffer.Append(kLineSeparator);
966
        aBpd->AppendUnichar(kLineSeparator);
867
        ResolveParagraphWithinBlock(aBlockFrame);
967
        ResolveParagraphWithinBlock(aBlockFrame, aBpd);
868
      } else { 
968
      } else { 
869
        // other frame type -- see the Unicode Bidi Algorithm:
969
        // other frame type -- see the Unicode Bidi Algorithm:
870
        // "...inline objects (such as graphics) are treated as if they are ...
970
        // "...inline objects (such as graphics) are treated as if they are ...
871
        // U+FFFC"
971
        // U+FFFC"
872
        mBuffer.Append(kObjectSubstitute);
972
        aBpd->AppendUnichar(kObjectSubstitute);
873
        if (!frame->GetStyleContext()->GetStyleDisplay()->IsInlineOutside()) {
973
        if (!frame->GetStyleContext()->GetStyleDisplay()->IsInlineOutside()) {
874
          // if it is not inline, end the paragraph
974
          // if it is not inline, end the paragraph
875
          ResolveParagraphWithinBlock(aBlockFrame);
975
          ResolveParagraphWithinBlock(aBlockFrame, aBpd);
876
        }
976
        }
877
      }
977
      }
878
    }
978
    }
879
    else {
979
    else {
880
      // For a non-leaf frame, recurse into TraverseFrames
980
      // For a non-leaf frame, recurse into TraverseFrames
881
      nsIFrame* kid = frame->GetFirstChild(nsnull);
981
      nsIFrame* kid = frame->GetFirstChild(nsnull);
882
      TraverseFrames(aBlockFrame, kid);
982
      TraverseFrames(aBlockFrame, kid, aBpd);
883
    }
983
    }
884
984
885
    // If the element is attributed by dir, indicate direction pop (add PDF frame)
985
    // If the element is attributed by dir, indicate direction pop (add PDF frame)
886
    if (ch != 0 && isLastFrame) {
986
    if (ch != 0 && isLastFrame) {
887
      // Add a dummy frame pointer representing a bidi control code after the
987
      // Add a dummy frame pointer representing a bidi control code after the
888
      // last frame of an element specifying embedding or override
988
      // last frame of an element specifying embedding or override
889
      mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
989
      aBpd->PopBidiControl();
890
      mBuffer.Append(kPDF);
891
      NS_ASSERTION(mEmbeddingStack.Length(), "embedding/override underflow");
892
      mEmbeddingStack.TruncateLength(mEmbeddingStack.Length() - 1);
893
    }
990
    }
894
    childFrame = nextSibling;
991
    childFrame = nextSibling;
895
  } while (childFrame);
992
  } while (childFrame);
896
}
993
}
897
994
898
void
995
void
899
nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame)
996
nsBidiPresUtils::ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame,
997
                                             BidiParagraphData* aBpd)
900
{
998
{
901
  nsIPresShell* shell;
999
  // pop all embeddings and overrides
902
  nsStyleContext* styleContext;
1000
  aBpd->ClearBidiControls();
903
1001
904
  if (mEmbeddingStack.Length() > 0) {
1002
  ResolveParagraph(aBlockFrame, aBpd);
905
    shell = aBlockFrame->PresContext()->PresShell();
906
    styleContext = aBlockFrame->GetStyleContext();
907
908
    // pop all embeddings and overrides
909
    for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) {
910
      mBuffer.Append(kPDF);
911
      mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
912
    }
913
  }
914
915
  ResolveParagraph(aBlockFrame);
916
1003
917
  // Clear the frame array and paragraph buffer, and restore the stored 
1004
  // Clear the frame array and paragraph buffer, and restore the stored 
918
  // embeddings and overrides
1005
  // embeddings and overrides
919
  mLogicalFrames.Clear();
1006
  aBpd->ResetData();
920
  mContentToFrameIndex.Clear();
921
  mBuffer.SetLength(0);
922
  if (mEmbeddingStack.Length() > 0) {
923
    for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) {
924
      mBuffer.Append(mEmbeddingStack[i]);
925
      mLogicalFrames.AppendElement(NS_BIDI_CONTROL_FRAME);
926
    }
927
  } 
928
}
1007
}
929
1008
930
void
1009
void
931
nsBidiPresUtils::ReorderFrames(nsIFrame*            aFirstFrameOnLine,
1010
nsBidiPresUtils::ReorderFrames(nsIFrame*            aFirstFrameOnLine,
932
                               PRInt32              aNumFramesOnLine)
1011
                               PRInt32              aNumFramesOnLine)
933
{
1012
{
934
  // If this line consists of a line frame, reorder the line frame's children.
1013
  // If this line consists of a line frame, reorder the line frame's children.
935
  if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) {
1014
  if (aFirstFrameOnLine->GetType() == nsGkAtoms::lineFrame) {
936
    aFirstFrameOnLine = aFirstFrameOnLine->GetFirstChild(nsnull);
1015
    aFirstFrameOnLine = aFirstFrameOnLine->GetFirstChild(nsnull);
937
    if (!aFirstFrameOnLine)
1016
    if (!aFirstFrameOnLine)
938
      return;
1017
      return;
939
    // All children of the line frame are on the first line. Setting aNumFramesOnLine
1018
    // All children of the line frame are on the first line. Setting aNumFramesOnLine
940
    // to -1 makes InitLogicalArrayFromLine look at all of them.
1019
    // to -1 makes InitLogicalArrayFromLine look at all of them.
941
    aNumFramesOnLine = -1;
1020
    aNumFramesOnLine = -1;
942
  }
1021
  }
943
1022
944
  InitLogicalArrayFromLine(aFirstFrameOnLine, aNumFramesOnLine);
1023
  BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine);
945
1024
  RepositionInlineFrames(&bld, aFirstFrameOnLine);
946
  PRBool isReordered;
947
  PRBool hasRTLFrames;
948
  Reorder(isReordered, hasRTLFrames);
949
  RepositionInlineFrames(aFirstFrameOnLine);
950
}
951
952
nsresult
953
nsBidiPresUtils::Reorder(PRBool& aReordered, PRBool& aHasRTLFrames)
954
{
955
  aReordered = PR_FALSE;
956
  aHasRTLFrames = PR_FALSE;
957
  PRInt32 count = mLogicalFrames.Length();
958
959
  if (mArraySize < count) {
960
    mArraySize = count << 1;
961
    if (mLevels) {
962
      delete[] mLevels;
963
      mLevels = nsnull;
964
    }
965
    if (mIndexMap) {
966
      delete[] mIndexMap;
967
      mIndexMap = nsnull;
968
    }
969
  }
970
  if (!mLevels) {
971
    mLevels = new PRUint8[mArraySize];
972
    if (!mLevels) {
973
      return NS_ERROR_OUT_OF_MEMORY;
974
    }
975
  }
976
  memset(mLevels, 0, sizeof(PRUint8) * mArraySize);
977
978
  nsIFrame* frame;
979
  PRInt32   i;
980
981
  for (i = 0; i < count; i++) {
982
    frame = mLogicalFrames[i];
983
    mLevels[i] = GetFrameEmbeddingLevel(frame);
984
    if (mLevels[i] & 1) {
985
      aHasRTLFrames = PR_TRUE;
986
    }      
987
  }
988
  if (!mIndexMap) {
989
    mIndexMap = new PRInt32[mArraySize];
990
  }
991
  if (!mIndexMap) {
992
    mSuccess = NS_ERROR_OUT_OF_MEMORY;
993
  }
994
  else {
995
    memset(mIndexMap, 0, sizeof(PRUint32) * mArraySize);
996
997
    mSuccess = mBidiEngine->ReorderVisual(mLevels, count, mIndexMap);
998
999
    if (NS_SUCCEEDED(mSuccess) ) {
1000
      mVisualFrames.Clear();
1001
1002
      for (i = 0; i < count; i++) {
1003
        mVisualFrames.AppendElement(mLogicalFrames[mIndexMap[i]]);
1004
        if (i != mIndexMap[i]) {
1005
          aReordered = PR_TRUE;
1006
        }
1007
      }
1008
    } // NS_SUCCEEDED(mSuccess)
1009
  } // indexMap
1010
1011
  if (NS_FAILED(mSuccess) ) {
1012
    aReordered = PR_FALSE;
1013
  }
1014
  return mSuccess;
1015
}
1025
}
1016
1026
1017
nsBidiLevel
1027
nsBidiLevel
1018
nsBidiPresUtils::GetFrameEmbeddingLevel(nsIFrame* aFrame)
1028
nsBidiPresUtils::GetFrameEmbeddingLevel(nsIFrame* aFrame)
1019
{
1029
{
1020
  nsIFrame* firstLeaf = aFrame;
1030
  nsIFrame* firstLeaf = aFrame;
1021
  while (!IsBidiLeaf(firstLeaf)) {
1031
  while (!IsBidiLeaf(firstLeaf)) {
1022
    nsIFrame* firstChild = firstLeaf->GetFirstChild(nsnull);
1032
    nsIFrame* firstChild = firstLeaf->GetFirstChild(nsnull);
 Lines 1036-1052   nsBidiPresUtils::GetFrameBaseLevel(nsIFr Link Here 
1036
  }
1046
  }
1037
  return NS_GET_BASE_LEVEL(firstLeaf);
1047
  return NS_GET_BASE_LEVEL(firstLeaf);
1038
}
1048
}
1039
1049
1040
void
1050
void
1041
nsBidiPresUtils::IsLeftOrRightMost(nsIFrame*              aFrame,
1051
nsBidiPresUtils::IsLeftOrRightMost(nsIFrame*              aFrame,
1042
                                   nsContinuationStates*  aContinuationStates,
1052
                                   nsContinuationStates*  aContinuationStates,
1043
                                   PRBool&                aIsLeftMost /* out */,
1053
                                   PRBool&                aIsLeftMost /* out */,
1044
                                   PRBool&                aIsRightMost /* out */) const
1054
                                   PRBool&                aIsRightMost /* out */)
1045
{
1055
{
1046
  const nsStyleVisibility* vis = aFrame->GetStyleVisibility();
1056
  const nsStyleVisibility* vis = aFrame->GetStyleVisibility();
1047
  PRBool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection);
1057
  PRBool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection);
1048
1058
1049
  /*
1059
  /*
1050
   * Since we lay out frames from left to right (in both LTR and RTL), visiting a
1060
   * Since we lay out frames from left to right (in both LTR and RTL), visiting a
1051
   * frame with 'mFirstVisualFrame == nsnull', means it's the first appearance of
1061
   * frame with 'mFirstVisualFrame == nsnull', means it's the first appearance of
1052
   * one of its continuation chain frames on the line.
1062
   * one of its continuation chain frames on the line.
 Lines 1130-1146   nsBidiPresUtils::IsLeftOrRightMost(nsIFr Link Here 
1130
  // Reduce number of remaining frames of the continuation chain on the line.
1140
  // Reduce number of remaining frames of the continuation chain on the line.
1131
  firstFrameState->mFrameCount--;
1141
  firstFrameState->mFrameCount--;
1132
}
1142
}
1133
1143
1134
void
1144
void
1135
nsBidiPresUtils::RepositionFrame(nsIFrame*              aFrame,
1145
nsBidiPresUtils::RepositionFrame(nsIFrame*              aFrame,
1136
                                 PRBool                 aIsOddLevel,
1146
                                 PRBool                 aIsOddLevel,
1137
                                 nscoord&               aLeft,
1147
                                 nscoord&               aLeft,
1138
                                 nsContinuationStates*  aContinuationStates) const
1148
                                 nsContinuationStates*  aContinuationStates)
1139
{
1149
{
1140
  if (!aFrame)
1150
  if (!aFrame)
1141
    return;
1151
    return;
1142
1152
1143
  PRBool isLeftMost, isRightMost;
1153
  PRBool isLeftMost, isRightMost;
1144
  IsLeftOrRightMost(aFrame,
1154
  IsLeftOrRightMost(aFrame,
1145
                    aContinuationStates,
1155
                    aContinuationStates,
1146
                    isLeftMost /* out */,
1156
                    isLeftMost /* out */,
 Lines 1215-1231   nsBidiPresUtils::RepositionFrame(nsIFram Link Here 
1215
  aFrame->SetRect(nsRect(start, rect.y, aLeft - start, rect.height));
1225
  aFrame->SetRect(nsRect(start, rect.y, aLeft - start, rect.height));
1216
1226
1217
  if (isRightMost)
1227
  if (isRightMost)
1218
    aLeft += margin.right;
1228
    aLeft += margin.right;
1219
}
1229
}
1220
1230
1221
void
1231
void
1222
nsBidiPresUtils::InitContinuationStates(nsIFrame*              aFrame,
1232
nsBidiPresUtils::InitContinuationStates(nsIFrame*              aFrame,
1223
                                        nsContinuationStates*  aContinuationStates) const
1233
                                        nsContinuationStates*  aContinuationStates)
1224
{
1234
{
1225
  nsFrameContinuationState* state = aContinuationStates->PutEntry(aFrame);
1235
  nsFrameContinuationState* state = aContinuationStates->PutEntry(aFrame);
1226
  state->mFirstVisualFrame = nsnull;
1236
  state->mFirstVisualFrame = nsnull;
1227
  state->mFrameCount = 0;
1237
  state->mFrameCount = 0;
1228
1238
1229
  if (!IsBidiLeaf(aFrame)) {
1239
  if (!IsBidiLeaf(aFrame)) {
1230
    // Continue for child frames
1240
    // Continue for child frames
1231
    nsIFrame* frame;
1241
    nsIFrame* frame;
 Lines 1234-1398   nsBidiPresUtils::InitContinuationStates( Link Here 
1234
         frame = frame->GetNextSibling()) {
1244
         frame = frame->GetNextSibling()) {
1235
      InitContinuationStates(frame,
1245
      InitContinuationStates(frame,
1236
                             aContinuationStates);
1246
                             aContinuationStates);
1237
    }
1247
    }
1238
  }
1248
  }
1239
}
1249
}
1240
1250
1241
void
1251
void
1242
nsBidiPresUtils::RepositionInlineFrames(nsIFrame* aFirstChild) const
1252
nsBidiPresUtils::RepositionInlineFrames(BidiLineData *aBld,
1253
                                        nsIFrame* aFirstChild)
1243
{
1254
{
1244
  const nsStyleVisibility* vis = aFirstChild->GetStyleVisibility();
1255
  const nsStyleVisibility* vis = aFirstChild->GetStyleVisibility();
1245
  PRBool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection);
1256
  PRBool isLTR = (NS_STYLE_DIRECTION_LTR == vis->mDirection);
1246
  nscoord leftSpace = 0;
1257
  nscoord leftSpace = 0;
1247
1258
1248
  // This method is called from nsBlockFrame::PlaceLine via the call to
1259
  // This method is called from nsBlockFrame::PlaceLine via the call to
1249
  // bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines
1260
  // bidiUtils->ReorderFrames, so this is guaranteed to be after the inlines
1250
  // have been reflowed, which is required for GetUsedMargin/Border/Padding
1261
  // have been reflowed, which is required for GetUsedMargin/Border/Padding
1251
  nsMargin margin = aFirstChild->GetUsedMargin();
1262
  nsMargin margin = aFirstChild->GetUsedMargin();
1252
  if (!aFirstChild->GetPrevContinuation() &&
1263
  if (!aFirstChild->GetPrevContinuation() &&
1253
      !nsLayoutUtils::FrameIsNonFirstInIBSplit(aFirstChild))
1264
      !nsLayoutUtils::FrameIsNonFirstInIBSplit(aFirstChild))
1254
    leftSpace = isLTR ? margin.left : margin.right;
1265
    leftSpace = isLTR ? margin.left : margin.right;
1255
1266
1256
  nscoord left = aFirstChild->GetPosition().x - leftSpace;
1267
  nscoord left = aFirstChild->GetPosition().x - leftSpace;
1257
  nsIFrame* frame;
1268
  nsIFrame* frame;
1258
  PRInt32 count = mVisualFrames.Length();
1269
  PRInt32 count = aBld->mVisualFrames.Length();
1259
  PRInt32 index;
1270
  PRInt32 index;
1260
  nsContinuationStates continuationStates;
1271
  nsContinuationStates continuationStates;
1261
1272
1262
  continuationStates.Init();
1273
  continuationStates.Init();
1263
1274
1264
  // Initialize continuation states to (nsnull, 0) for
1275
  // Initialize continuation states to (nsnull, 0) for
1265
  // each frame on the line.
1276
  // each frame on the line.
1266
  for (index = 0; index < count; index++) {
1277
  for (index = 0; index < count; index++) {
1267
    InitContinuationStates(mVisualFrames[index], &continuationStates);
1278
    InitContinuationStates(aBld->VisualFrameAt(index), &continuationStates);
1268
  }
1279
  }
1269
1280
1270
  // Reposition frames in visual order
1281
  // Reposition frames in visual order
1271
  for (index = 0; index < count; index++) {
1282
  for (index = 0; index < count; index++) {
1272
    frame = mVisualFrames[index];
1283
    frame = aBld->VisualFrameAt(index);
1273
    RepositionFrame(frame,
1284
    RepositionFrame(frame,
1274
                    (mLevels[mIndexMap[index]] & 1),
1285
                    (aBld->mLevels[aBld->mIndexMap[index]] & 1),
1275
                    left,
1286
                    left,
1276
                    &continuationStates);
1287
                    &continuationStates);
1277
  } // for
1288
  } // for
1278
}
1289
}
1279
1290
1280
void 
1281
nsBidiPresUtils::InitLogicalArrayFromLine(nsIFrame* aFirstFrameOnLine,
1282
                                          PRInt32   aNumFramesOnLine) {
1283
  mLogicalFrames.Clear();
1284
  for (nsIFrame* frame = aFirstFrameOnLine;
1285
       frame && aNumFramesOnLine--;
1286
       frame = frame->GetNextSibling()) {
1287
    mLogicalFrames.AppendElement(frame);
1288
  }
1289
}
1290
1291
PRBool
1291
PRBool
1292
nsBidiPresUtils::CheckLineOrder(nsIFrame*  aFirstFrameOnLine,
1292
nsBidiPresUtils::CheckLineOrder(nsIFrame*  aFirstFrameOnLine,
1293
                                PRInt32    aNumFramesOnLine,
1293
                                PRInt32    aNumFramesOnLine,
1294
                                nsIFrame** aFirstVisual,
1294
                                nsIFrame** aFirstVisual,
1295
                                nsIFrame** aLastVisual)
1295
                                nsIFrame** aLastVisual)
1296
{
1296
{
1297
  InitLogicalArrayFromLine(aFirstFrameOnLine, aNumFramesOnLine);
1297
  BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine);
1298
  
1298
  PRInt32 count = bld.FrameCount();
1299
  PRBool isReordered;
1300
  PRBool hasRTLFrames;
1301
  Reorder(isReordered, hasRTLFrames);
1302
  PRInt32 count = mLogicalFrames.Length();
1303
  
1299
  
1304
  if (aFirstVisual) {
1300
  if (aFirstVisual) {
1305
    *aFirstVisual = mVisualFrames[0];
1301
    *aFirstVisual = bld.VisualFrameAt(0);
1306
  }
1302
  }
1307
  if (aLastVisual) {
1303
  if (aLastVisual) {
1308
    *aLastVisual = mVisualFrames[count-1];
1304
    *aLastVisual = bld.VisualFrameAt(count-1);
1309
  }
1305
  }
1310
  
1306
  
1311
  // If there's an RTL frame, assume the line is reordered
1307
  return bld.mIsReordered;
1312
  return isReordered || hasRTLFrames;
1313
}
1308
}
1314
1309
1315
nsIFrame*
1310
nsIFrame*
1316
nsBidiPresUtils::GetFrameToRightOf(const nsIFrame*  aFrame,
1311
nsBidiPresUtils::GetFrameToRightOf(const nsIFrame*  aFrame,
1317
                                   nsIFrame*        aFirstFrameOnLine,
1312
                                   nsIFrame*        aFirstFrameOnLine,
1318
                                   PRInt32          aNumFramesOnLine)
1313
                                   PRInt32          aNumFramesOnLine)
1319
{
1314
{
1320
  InitLogicalArrayFromLine(aFirstFrameOnLine, aNumFramesOnLine);
1315
  BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine);
1321
  
1316
1322
  PRBool isReordered;
1317
  PRInt32 count = bld.mVisualFrames.Length();
1323
  PRBool hasRTLFrames;
1324
  Reorder(isReordered, hasRTLFrames);
1325
  PRInt32 count = mVisualFrames.Length();
1326
1318
1327
  if (aFrame == nsnull)
1319
  if (aFrame == nsnull)
1328
    return mVisualFrames[0];
1320
    return bld.VisualFrameAt(0);
1329
  
1321
  
1330
  for (PRInt32 i = 0; i < count - 1; i++) {
1322
  for (PRInt32 i = 0; i < count - 1; i++) {
1331
    if (mVisualFrames[i] == aFrame) {
1323
    if (bld.VisualFrameAt(i) == aFrame) {
1332
      return mVisualFrames[i+1];
1324
      return bld.VisualFrameAt(i+1);
1333
    }
1325
    }
1334
  }
1326
  }
1335
  
1327
  
1336
  return nsnull;
1328
  return nsnull;
1337
}
1329
}
1338
1330
1339
nsIFrame*
1331
nsIFrame*
1340
nsBidiPresUtils::GetFrameToLeftOf(const nsIFrame*  aFrame,
1332
nsBidiPresUtils::GetFrameToLeftOf(const nsIFrame*  aFrame,
1341
                                  nsIFrame*        aFirstFrameOnLine,
1333
                                  nsIFrame*        aFirstFrameOnLine,
1342
                                  PRInt32          aNumFramesOnLine)
1334
                                  PRInt32          aNumFramesOnLine)
1343
{
1335
{
1344
  InitLogicalArrayFromLine(aFirstFrameOnLine, aNumFramesOnLine);
1336
  BidiLineData bld(aFirstFrameOnLine, aNumFramesOnLine);
1345
  
1337
1346
  PRBool isReordered;
1338
  PRInt32 count = bld.mVisualFrames.Length();
1347
  PRBool hasRTLFrames;
1348
  Reorder(isReordered, hasRTLFrames);
1349
  PRInt32 count = mVisualFrames.Length();
1350
  
1339
  
1351
  if (aFrame == nsnull)
1340
  if (aFrame == nsnull)
1352
    return mVisualFrames[count-1];
1341
    return bld.VisualFrameAt(count-1);
1353
  
1342
  
1354
  for (PRInt32 i = 1; i < count; i++) {
1343
  for (PRInt32 i = 1; i < count; i++) {
1355
    if (mVisualFrames[i] == aFrame) {
1344
    if (bld.VisualFrameAt(i) == aFrame) {
1356
      return mVisualFrames[i-1];
1345
      return bld.VisualFrameAt(i-1);
1357
    }
1346
    }
1358
  }
1347
  }
1359
  
1348
  
1360
  return nsnull;
1349
  return nsnull;
1361
}
1350
}
1362
1351
1363
inline void
1352
inline nsresult
1364
nsBidiPresUtils::EnsureBidiContinuation(nsIFrame*       aFrame,
1353
nsBidiPresUtils::EnsureBidiContinuation(nsIFrame*       aFrame,
1365
                                        nsIFrame**      aNewFrame,
1354
                                        nsIFrame**      aNewFrame,
1366
                                        PRInt32&        aFrameIndex,
1355
                                        PRInt32&        aFrameIndex,
1367
                                        PRInt32         aStart,
1356
                                        PRInt32         aStart,
1368
                                        PRInt32         aEnd)
1357
                                        PRInt32         aEnd)
1369
{
1358
{
1370
  NS_PRECONDITION(aNewFrame, "null OUT ptr");
1359
  NS_PRECONDITION(aNewFrame, "null OUT ptr");
1371
  NS_PRECONDITION(aFrame, "aFrame is null");
1360
  NS_PRECONDITION(aFrame, "aFrame is null");
1372
1361
1373
  aFrame->AdjustOffsetsForBidi(aStart, aEnd);
1362
  aFrame->AdjustOffsetsForBidi(aStart, aEnd);
1374
  mSuccess = CreateContinuation(aFrame, aNewFrame, PR_FALSE);
1363
  return CreateContinuation(aFrame, aNewFrame, PR_FALSE);
1375
}
1364
}
1376
1365
1377
void
1366
void
1378
nsBidiPresUtils::RemoveBidiContinuation(nsIFrame*       aFrame,
1367
nsBidiPresUtils::RemoveBidiContinuation(BidiParagraphData *aBpd,
1368
                                        nsIFrame*       aFrame,
1379
                                        PRInt32         aFirstIndex,
1369
                                        PRInt32         aFirstIndex,
1380
                                        PRInt32         aLastIndex,
1370
                                        PRInt32         aLastIndex,
1381
                                        PRInt32&        aOffset) const
1371
                                        PRInt32&        aOffset)
1382
{
1372
{
1383
  FrameProperties props = aFrame->Properties();
1373
  FrameProperties props = aFrame->Properties();
1384
  nsBidiLevel embeddingLevel =
1374
  nsBidiLevel embeddingLevel =
1385
    (nsBidiLevel)NS_PTR_TO_INT32(props.Get(nsIFrame::EmbeddingLevelProperty()));
1375
    (nsBidiLevel)NS_PTR_TO_INT32(props.Get(nsIFrame::EmbeddingLevelProperty()));
1386
  nsBidiLevel baseLevel =
1376
  nsBidiLevel baseLevel =
1387
    (nsBidiLevel)NS_PTR_TO_INT32(props.Get(nsIFrame::BaseLevelProperty()));
1377
    (nsBidiLevel)NS_PTR_TO_INT32(props.Get(nsIFrame::BaseLevelProperty()));
1388
1378
1389
  for (PRInt32 index = aFirstIndex + 1; index <= aLastIndex; index++) {
1379
  for (PRInt32 index = aFirstIndex + 1; index <= aLastIndex; index++) {
1390
    nsIFrame* frame = mLogicalFrames[index];
1380
    nsIFrame* frame = aBpd->FrameAt(index);
1391
    if (frame == NS_BIDI_CONTROL_FRAME) {
1381
    if (frame == NS_BIDI_CONTROL_FRAME) {
1392
      ++aOffset;
1382
      ++aOffset;
1393
    }
1383
    }
1394
    else {
1384
    else {
1395
      // Make the frame and its continuation ancestors fluid,
1385
      // Make the frame and its continuation ancestors fluid,
1396
      // so they can be reused or deleted by normal reflow code
1386
      // so they can be reused or deleted by normal reflow code
1397
      FrameProperties frameProps = frame->Properties();
1387
      FrameProperties frameProps = frame->Properties();
1398
      frameProps.Set(nsIFrame::EmbeddingLevelProperty(),
1388
      frameProps.Set(nsIFrame::EmbeddingLevelProperty(),
 Lines 1476-1492   nsBidiPresUtils::FormatUnicodeText(nsPre Link Here 
1476
  }
1466
  }
1477
1467
1478
  StripBidiControlCharacters(aText, aTextLength);
1468
  StripBidiControlCharacters(aText, aTextLength);
1479
  return rv;
1469
  return rv;
1480
}
1470
}
1481
1471
1482
void
1472
void
1483
nsBidiPresUtils::StripBidiControlCharacters(PRUnichar* aText,
1473
nsBidiPresUtils::StripBidiControlCharacters(PRUnichar* aText,
1484
                                            PRInt32&   aTextLength) const
1474
                                            PRInt32&   aTextLength)
1485
{
1475
{
1486
  if ( (nsnull == aText) || (aTextLength < 1) ) {
1476
  if ( (nsnull == aText) || (aTextLength < 1) ) {
1487
    return;
1477
    return;
1488
  }
1478
  }
1489
1479
1490
  PRInt32 stripLen = 0;
1480
  PRInt32 stripLen = 0;
1491
1481
1492
  for (PRInt32 i = 0; i < aTextLength; i++) {
1482
  for (PRInt32 i = 0; i < aTextLength; i++) {
 Lines 1519-1561   RemoveDiacritics(PRUnichar* aText, Link Here 
1519
    }
1509
    }
1520
    aTextLength = i - offset;
1510
    aTextLength = i - offset;
1521
    aText[aTextLength] = 0;
1511
    aText[aTextLength] = 0;
1522
  }
1512
  }
1523
}
1513
}
1524
#endif
1514
#endif
1525
1515
1526
void
1516
void
1527
nsBidiPresUtils::CalculateCharType(PRInt32& aOffset,
1517
nsBidiPresUtils::CalculateCharType(nsBidi* aBidiEngine,
1518
                                   const PRUnichar* aText,
1519
                                   PRInt32& aOffset,
1528
                                   PRInt32  aCharTypeLimit,
1520
                                   PRInt32  aCharTypeLimit,
1529
                                   PRInt32& aRunLimit,
1521
                                   PRInt32& aRunLimit,
1530
                                   PRInt32& aRunLength,
1522
                                   PRInt32& aRunLength,
1531
                                   PRInt32& aRunCount,
1523
                                   PRInt32& aRunCount,
1532
                                   PRUint8& aCharType,
1524
                                   PRUint8& aCharType,
1533
                                   PRUint8& aPrevCharType) const
1525
                                   PRUint8& aPrevCharType)
1534
1526
1535
{
1527
{
1536
  PRBool     strongTypeFound = PR_FALSE;
1528
  PRBool     strongTypeFound = PR_FALSE;
1537
  PRInt32    offset;
1529
  PRInt32    offset;
1538
  nsCharType charType;
1530
  nsCharType charType;
1539
1531
1540
  aCharType = eCharType_OtherNeutral;
1532
  aCharType = eCharType_OtherNeutral;
1541
1533
1542
  for (offset = aOffset; offset < aCharTypeLimit; offset++) {
1534
  for (offset = aOffset; offset < aCharTypeLimit; offset++) {
1543
    // Make sure we give RTL chartype to all characters that would be classified
1535
    // Make sure we give RTL chartype to all characters that would be classified
1544
    // as Right-To-Left by a bidi platform.
1536
    // as Right-To-Left by a bidi platform.
1545
    // (May differ from the UnicodeData, eg we set RTL chartype to some NSMs.)
1537
    // (May differ from the UnicodeData, eg we set RTL chartype to some NSMs.)
1546
    if (IS_HEBREW_CHAR(mBuffer[offset]) ) {
1538
    if (IS_HEBREW_CHAR(aText[offset]) ) {
1547
      charType = eCharType_RightToLeft;
1539
      charType = eCharType_RightToLeft;
1548
    }
1540
    }
1549
    else if (IS_ARABIC_ALPHABETIC(mBuffer[offset]) ) {
1541
    else if (IS_ARABIC_ALPHABETIC(aText[offset]) ) {
1550
      charType = eCharType_RightToLeftArabic;
1542
      charType = eCharType_RightToLeftArabic;
1551
    }
1543
    }
1552
    else {
1544
    else {
1553
      mBidiEngine->GetCharTypeAt(offset, &charType);
1545
      aBidiEngine->GetCharTypeAt(offset, &charType);
1554
    }
1546
    }
1555
1547
1556
    if (!CHARTYPE_IS_WEAK(charType) ) {
1548
    if (!CHARTYPE_IS_WEAK(charType) ) {
1557
1549
1558
      if (strongTypeFound
1550
      if (strongTypeFound
1559
          && (charType != aPrevCharType)
1551
          && (charType != aPrevCharType)
1560
          && (CHARTYPE_IS_RTL(charType) || CHARTYPE_IS_RTL(aPrevCharType) ) ) {
1552
          && (CHARTYPE_IS_RTL(charType) || CHARTYPE_IS_RTL(aPrevCharType) ) ) {
1561
        // Stop at this point to ensure uni-directionality of the text
1553
        // Stop at this point to ensure uni-directionality of the text
 Lines 1588-1616   nsBidiPresUtils::CalculateCharType(PRInt Link Here 
1588
nsresult nsBidiPresUtils::ProcessText(const PRUnichar*       aText,
1580
nsresult nsBidiPresUtils::ProcessText(const PRUnichar*       aText,
1589
                                      PRInt32                aLength,
1581
                                      PRInt32                aLength,
1590
                                      nsBidiDirection        aBaseDirection,
1582
                                      nsBidiDirection        aBaseDirection,
1591
                                      nsPresContext*         aPresContext,
1583
                                      nsPresContext*         aPresContext,
1592
                                      BidiProcessor&         aprocessor,
1584
                                      BidiProcessor&         aprocessor,
1593
                                      Mode                   aMode,
1585
                                      Mode                   aMode,
1594
                                      nsBidiPositionResolve* aPosResolve,
1586
                                      nsBidiPositionResolve* aPosResolve,
1595
                                      PRInt32                aPosResolveCount,
1587
                                      PRInt32                aPosResolveCount,
1596
                                      nscoord*               aWidth)
1588
                                      nscoord*               aWidth,
1589
                                      nsBidi*                aBidiEngine)
1597
{
1590
{
1598
  NS_ASSERTION((aPosResolve == nsnull) != (aPosResolveCount > 0), "Incorrect aPosResolve / aPosResolveCount arguments");
1591
  NS_ASSERTION((aPosResolve == nsnull) != (aPosResolveCount > 0), "Incorrect aPosResolve / aPosResolveCount arguments");
1599
1592
1600
  PRInt32 runCount;
1593
  PRInt32 runCount;
1601
1594
1602
  mBuffer.Assign(aText, aLength);
1595
  nsAutoString textBuffer(aText, aLength);
1603
1596
1604
  nsresult rv = mBidiEngine->SetPara(mBuffer.get(), aLength, aBaseDirection, nsnull);
1597
  nsresult rv = aBidiEngine->SetPara(aText, aLength, aBaseDirection, nsnull);
1605
  if (NS_FAILED(rv))
1598
  if (NS_FAILED(rv))
1606
    return rv;
1599
    return rv;
1607
1600
1608
  rv = mBidiEngine->CountRuns(&runCount);
1601
  rv = aBidiEngine->CountRuns(&runCount);
1609
  if (NS_FAILED(rv))
1602
  if (NS_FAILED(rv))
1610
    return rv;
1603
    return rv;
1611
1604
1612
  nscoord xOffset = 0;
1605
  nscoord xOffset = 0;
1613
  nscoord width, xEndRun;
1606
  nscoord width, xEndRun;
1614
  nscoord totalWidth = 0;
1607
  nscoord totalWidth = 0;
1615
  PRInt32 i, start, limit, length;
1608
  PRInt32 i, start, limit, length;
1616
  PRUint32 visualStart = 0;
1609
  PRUint32 visualStart = 0;
 Lines 1621-1641   nsresult nsBidiPresUtils::ProcessText(co Link Here 
1621
  for(int nPosResolve=0; nPosResolve < aPosResolveCount; ++nPosResolve)
1614
  for(int nPosResolve=0; nPosResolve < aPosResolveCount; ++nPosResolve)
1622
  {
1615
  {
1623
    aPosResolve[nPosResolve].visualIndex = kNotFound;
1616
    aPosResolve[nPosResolve].visualIndex = kNotFound;
1624
    aPosResolve[nPosResolve].visualLeftTwips = kNotFound;
1617
    aPosResolve[nPosResolve].visualLeftTwips = kNotFound;
1625
    aPosResolve[nPosResolve].visualWidth = kNotFound;
1618
    aPosResolve[nPosResolve].visualWidth = kNotFound;
1626
  }
1619
  }
1627
1620
1628
  for (i = 0; i < runCount; i++) {
1621
  for (i = 0; i < runCount; i++) {
1629
    rv = mBidiEngine->GetVisualRun(i, &start, &length, &aBaseDirection);
1622
    rv = aBidiEngine->GetVisualRun(i, &start, &length, &aBaseDirection);
1630
    if (NS_FAILED(rv))
1623
    if (NS_FAILED(rv))
1631
      return rv;
1624
      return rv;
1632
1625
1633
    rv = mBidiEngine->GetLogicalRun(start, &limit, &level);
1626
    rv = aBidiEngine->GetLogicalRun(start, &limit, &level);
1634
    if (NS_FAILED(rv))
1627
    if (NS_FAILED(rv))
1635
      return rv;
1628
      return rv;
1636
1629
1637
    PRInt32 subRunLength = limit - start;
1630
    PRInt32 subRunLength = limit - start;
1638
    PRInt32 lineOffset = start;
1631
    PRInt32 lineOffset = start;
1639
    PRInt32 typeLimit = NS_MIN(limit, aLength);
1632
    PRInt32 typeLimit = NS_MIN(limit, aLength);
1640
    PRInt32 subRunCount = 1;
1633
    PRInt32 subRunCount = 1;
1641
    PRInt32 subRunLimit = typeLimit;
1634
    PRInt32 subRunLimit = typeLimit;
 Lines 1657-1673   nsresult nsBidiPresUtils::ProcessText(co Link Here 
1657
      width = aprocessor.GetWidth();
1650
      width = aprocessor.GetWidth();
1658
      xOffset += width;
1651
      xOffset += width;
1659
      xEndRun = xOffset;
1652
      xEndRun = xOffset;
1660
    }
1653
    }
1661
1654
1662
    while (subRunCount > 0) {
1655
    while (subRunCount > 0) {
1663
      // CalculateCharType can increment subRunCount if the run
1656
      // CalculateCharType can increment subRunCount if the run
1664
      // contains mixed character types
1657
      // contains mixed character types
1665
      CalculateCharType(lineOffset, typeLimit, subRunLimit, subRunLength, subRunCount, charType, prevType);
1658
      CalculateCharType(aBidiEngine, aText, lineOffset, typeLimit, subRunLimit, subRunLength, subRunCount, charType, prevType);
1666
      
1659
      
1667
      nsAutoString runVisualText;
1660
      nsAutoString runVisualText;
1668
      runVisualText.Assign(aText + start, subRunLength);
1661
      runVisualText.Assign(aText + start, subRunLength);
1669
      if (PRInt32(runVisualText.Length()) < subRunLength)
1662
      if (PRInt32(runVisualText.Length()) < subRunLength)
1670
        return NS_ERROR_OUT_OF_MEMORY;
1663
        return NS_ERROR_OUT_OF_MEMORY;
1671
      FormatUnicodeText(aPresContext, runVisualText.BeginWriting(), subRunLength,
1664
      FormatUnicodeText(aPresContext, runVisualText.BeginWriting(), subRunLength,
1672
                        (nsCharType)charType, level & 1);
1665
                        (nsCharType)charType, level & 1);
1673
1666
 Lines 1848-1866   nsresult nsBidiPresUtils::ProcessTextFor Link Here 
1848
                                                         Mode                   aMode,
1841
                                                         Mode                   aMode,
1849
                                                         nscoord                aX,
1842
                                                         nscoord                aX,
1850
                                                         nscoord                aY,
1843
                                                         nscoord                aY,
1851
                                                         nsBidiPositionResolve* aPosResolve,
1844
                                                         nsBidiPositionResolve* aPosResolve,
1852
                                                         PRInt32                aPosResolveCount,
1845
                                                         PRInt32                aPosResolveCount,
1853
                                                         nscoord*               aWidth)
1846
                                                         nscoord*               aWidth)
1854
{
1847
{
1855
  nsIRenderingContextBidiProcessor processor(&aRenderingContext, &aTextRunConstructionContext, nsPoint(aX, aY));
1848
  nsIRenderingContextBidiProcessor processor(&aRenderingContext, &aTextRunConstructionContext, nsPoint(aX, aY));
1856
1849
  nsBidi bidiEngine;
1857
  return ProcessText(aText, aLength, aBaseDirection, aPresContext, processor,
1850
  return ProcessText(aText, aLength, aBaseDirection, aPresContext, processor,
1858
                     aMode, aPosResolve, aPosResolveCount, aWidth);
1851
                     aMode, aPosResolve, aPosResolveCount, aWidth, &bidiEngine);
1859
}
1852
}
1860
1853
1861
/* static */
1854
/* static */
1862
void nsBidiPresUtils::WriteReverse(const PRUnichar* aSrc,
1855
void nsBidiPresUtils::WriteReverse(const PRUnichar* aSrc,
1863
                                   PRUint32 aSrcLength,
1856
                                   PRUint32 aSrcLength,
1864
                                   PRUnichar* aDest)
1857
                                   PRUnichar* aDest)
1865
{
1858
{
1866
  const PRUnichar* src = aSrc + aSrcLength;
1859
  const PRUnichar* src = aSrc + aSrcLength;
 Lines 1972-2026   void nsBidiPresUtils::CopyLogicalToVisua Link Here 
1972
      // no need to use the converter -- just copy the string in reverse order
1965
      // no need to use the converter -- just copy the string in reverse order
1973
      WriteReverse(fromBegin.get(), srcLength, toBegin.get());
1966
      WriteReverse(fromBegin.get(), srcLength, toBegin.get());
1974
    } else {
1967
    } else {
1975
      // if aOverride && aBaseDirection == NSBIDI_LTR, fall through to the
1968
      // if aOverride && aBaseDirection == NSBIDI_LTR, fall through to the
1976
      // simple copy
1969
      // simple copy
1977
      aDest.SetLength(0);
1970
      aDest.SetLength(0);
1978
    }
1971
    }
1979
  } else {
1972
  } else {
1973
    nsBidi bidiEngine;
1980
    if (!WriteLogicalToVisual(fromBegin.get(), srcLength, toBegin.get(),
1974
    if (!WriteLogicalToVisual(fromBegin.get(), srcLength, toBegin.get(),
1981
                             aBaseDirection, mBidiEngine)) {
1975
                             aBaseDirection, &bidiEngine)) {
1982
      aDest.SetLength(0);
1976
      aDest.SetLength(0);
1983
    }
1977
    }
1984
  }
1978
  }
1985
1979
1986
  if (aDest.IsEmpty()) {
1980
  if (aDest.IsEmpty()) {
1987
    // Either there was an error or the source is unidirectional
1981
    // Either there was an error or the source is unidirectional
1988
    //  left-to-right. In either case, just copy source to dest.
1982
    //  left-to-right. In either case, just copy source to dest.
1989
    CopyUnicodeTo(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd),
1983
    CopyUnicodeTo(aSource.BeginReading(fromBegin), aSource.EndReading(fromEnd),
1990
                  aDest);
1984
                  aDest);
1991
  }
1985
  }
1992
}
1986
}
1993
1994
PRUint32 nsBidiPresUtils::EstimateMemoryUsed()
1995
{
1996
  PRUint32 size = 0;
1997
1998
  size += sizeof(nsBidiPresUtils);
1999
  size += mBuffer.Length() * sizeof(PRUnichar);
2000
  size += moz_malloc_usable_size(mBidiEngine->mDirPropsMemory);
2001
  size += moz_malloc_usable_size(mBidiEngine->mLevelsMemory);
2002
  size += moz_malloc_usable_size(mBidiEngine->mRunsMemory);
2003
2004
  return size;
2005
}
2006
2007
static PLDHashOperator
2008
TraverseKey(nsISupports *aKey, PRInt32 aData, void *aUserArg)
2009
{
2010
  nsCycleCollectionTraversalCallback *cb =
2011
    static_cast<nsCycleCollectionTraversalCallback*>(aUserArg);
2012
  NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(*cb, "mContentToFrameIndex key");
2013
  cb->NoteXPCOMChild(aKey);
2014
  return PL_DHASH_NEXT;
2015
}
2016
2017
void nsBidiPresUtils::Traverse(nsCycleCollectionTraversalCallback &cb) const
2018
{
2019
  mContentToFrameIndex.EnumerateRead(TraverseKey, &cb);
2020
}
2021
2022
void nsBidiPresUtils::Unlink()
2023
{
2024
  mContentToFrameIndex.Clear();
2025
}
2026
#endif // IBMBIDI
1987
#endif // IBMBIDI
(-)a/layout/base/nsBidiPresUtils.h (-137 / +105 lines)
Line     Link Here 
 Lines 50-65    Link Here 
50
#include "nsDataHashtable.h"
50
#include "nsDataHashtable.h"
51
#include "nsBlockFrame.h"
51
#include "nsBlockFrame.h"
52
#include "nsTHashtable.h"
52
#include "nsTHashtable.h"
53
53
54
#ifdef DrawText
54
#ifdef DrawText
55
#undef DrawText
55
#undef DrawText
56
#endif
56
#endif
57
57
58
struct BidiParagraphData;
59
struct BidiLineData;
60
58
/**
61
/**
59
 * A structure representing some continuation state for each frame on the line,
62
 * A structure representing some continuation state for each frame on the line,
60
 * used to determine the first and the last continuation frame for each
63
 * used to determine the first and the last continuation frame for each
61
 * continuation chain on the line.
64
 * continuation chain on the line.
62
 */
65
 */
63
struct nsFrameContinuationState : public nsVoidPtrHashKey
66
struct nsFrameContinuationState : public nsVoidPtrHashKey
64
{
67
{
65
  nsFrameContinuationState(const void *aFrame) : nsVoidPtrHashKey(aFrame) {}
68
  nsFrameContinuationState(const void *aFrame) : nsVoidPtrHashKey(aFrame) {}
 Lines 169-209   public: Link Here 
169
  /**
172
  /**
170
   * Make Bidi engine calculate the embedding levels of the frames that are
173
   * Make Bidi engine calculate the embedding levels of the frames that are
171
   * descendants of a given block frame.
174
   * descendants of a given block frame.
172
   *
175
   *
173
   * @param aBlockFrame          The block frame
176
   * @param aBlockFrame          The block frame
174
   *
177
   *
175
   *  @lina 06/18/2000
178
   *  @lina 06/18/2000
176
   */
179
   */
177
  nsresult Resolve(nsBlockFrame* aBlockFrame);
180
  static nsresult Resolve(nsBlockFrame* aBlockFrame);
178
  void ResolveParagraph(nsBlockFrame* aBlockFrame);
181
  static nsresult ResolveParagraph(nsBlockFrame* aBlockFrame,
179
  void ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame);
182
                                   BidiParagraphData* aBpd);
183
  static void ResolveParagraphWithinBlock(nsBlockFrame* aBlockFrame,
184
                                          BidiParagraphData* aBpd);
180
185
181
  /**
186
  /**
182
   * Reorder this line using Bidi engine.
187
   * Reorder this line using Bidi engine.
183
   * Update frame array, following the new visual sequence.
188
   * Update frame array, following the new visual sequence.
184
   * 
189
   * 
185
   * @lina 05/02/2000
190
   * @lina 05/02/2000
186
   */
191
   */
187
  void ReorderFrames(nsIFrame*            aFirstFrameOnLine,
192
  static void ReorderFrames(nsIFrame*            aFirstFrameOnLine,
188
                     PRInt32              aNumFramesOnLine);
193
                            PRInt32              aNumFramesOnLine);
189
194
190
  /**
195
  /**
191
   * Format Unicode text, taking into account bidi capabilities
196
   * Format Unicode text, taking into account bidi capabilities
192
   * of the platform. The formatting includes: reordering, Arabic shaping,
197
   * of the platform. The formatting includes: reordering, Arabic shaping,
193
   * symmetric and numeric swapping, removing control characters.
198
   * symmetric and numeric swapping, removing control characters.
194
   *
199
   *
195
   * @lina 06/18/2000 
200
   * @lina 06/18/2000 
196
   */
201
   */
197
  nsresult FormatUnicodeText(nsPresContext* aPresContext,
202
  static nsresult FormatUnicodeText(nsPresContext* aPresContext,
198
                             PRUnichar*      aText,
203
                                    PRUnichar*      aText,
199
                             PRInt32&        aTextLength,
204
                                    PRInt32&        aTextLength,
200
                             nsCharType      aCharType,
205
                                    nsCharType      aCharType,
201
                             PRBool          aIsOddLevel);
206
                                    PRBool          aIsOddLevel);
202
207
203
  /**
208
  /**
204
   * Reorder plain text using the Unicode Bidi algorithm and send it to
209
   * Reorder plain text using the Unicode Bidi algorithm and send it to
205
   * a rendering context for rendering.
210
   * a rendering context for rendering.
206
   *
211
   *
207
   * @param[in] aText  the string to be rendered (in logical order)
212
   * @param[in] aText  the string to be rendered (in logical order)
208
   * @param aLength the number of characters in the string
213
   * @param aLength the number of characters in the string
209
   * @param aBaseDirection the base direction of the string
214
   * @param aBaseDirection the base direction of the string
 Lines 212-289   public: Link Here 
212
   * @param aPresContext the presentation context
217
   * @param aPresContext the presentation context
213
   * @param aRenderingContext the rendering context to render to
218
   * @param aRenderingContext the rendering context to render to
214
   * @param aTextRunConstructionContext the rendering context to be used to construct the textrun (affects font hinting)
219
   * @param aTextRunConstructionContext the rendering context to be used to construct the textrun (affects font hinting)
215
   * @param aX the x-coordinate to render the string
220
   * @param aX the x-coordinate to render the string
216
   * @param aY the y-coordinate to render the string
221
   * @param aY the y-coordinate to render the string
217
   * @param[in,out] aPosResolve array of logical positions to resolve into visual positions; can be nsnull if this functionality is not required
222
   * @param[in,out] aPosResolve array of logical positions to resolve into visual positions; can be nsnull if this functionality is not required
218
   * @param aPosResolveCount number of items in the aPosResolve array
223
   * @param aPosResolveCount number of items in the aPosResolve array
219
   */
224
   */
220
  nsresult RenderText(const PRUnichar*       aText,
225
  static nsresult RenderText(const PRUnichar*       aText,
221
                      PRInt32                aLength,
226
                             PRInt32                aLength,
222
                      nsBidiDirection        aBaseDirection,
227
                             nsBidiDirection        aBaseDirection,
223
                      nsPresContext*         aPresContext,
228
                             nsPresContext*         aPresContext,
224
                      nsIRenderingContext&   aRenderingContext,
229
                             nsIRenderingContext&   aRenderingContext,
225
                      nsIRenderingContext&   aTextRunConstructionContext,
230
                             nsIRenderingContext&   aTextRunConstructionContext,
226
                      nscoord                aX,
231
                             nscoord                aX,
227
                      nscoord                aY,
232
                             nscoord                aY,
228
                      nsBidiPositionResolve* aPosResolve = nsnull,
233
                             nsBidiPositionResolve* aPosResolve = nsnull,
229
                      PRInt32                aPosResolveCount = 0)
234
                             PRInt32                aPosResolveCount = 0)
230
  {
235
  {
231
    return ProcessTextForRenderingContext(aText, aLength, aBaseDirection, aPresContext, aRenderingContext,
236
    return ProcessTextForRenderingContext(aText, aLength, aBaseDirection, aPresContext, aRenderingContext,
232
                                          aTextRunConstructionContext, MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nsnull);
237
                                          aTextRunConstructionContext, MODE_DRAW, aX, aY, aPosResolve, aPosResolveCount, nsnull);
233
  }
238
  }
234
  
239
  
235
  nscoord MeasureTextWidth(const PRUnichar*     aText,
240
  static nscoord MeasureTextWidth(const PRUnichar*     aText,
236
                           PRInt32              aLength,
241
                                  PRInt32              aLength,
237
                           nsBidiDirection      aBaseDirection,
242
                                  nsBidiDirection      aBaseDirection,
238
                           nsPresContext*       aPresContext,
243
                                  nsPresContext*       aPresContext,
239
                           nsIRenderingContext& aRenderingContext)
244
                                  nsIRenderingContext& aRenderingContext)
240
  {
245
  {
241
    nscoord length;
246
    nscoord length;
242
    nsresult rv = ProcessTextForRenderingContext(aText, aLength, aBaseDirection, aPresContext,
247
    nsresult rv = ProcessTextForRenderingContext(aText, aLength, aBaseDirection, aPresContext,
243
                                                 aRenderingContext, aRenderingContext,
248
                                                 aRenderingContext, aRenderingContext,
244
                                                 MODE_MEASURE, 0, 0, nsnull, 0, &length);
249
                                                 MODE_MEASURE, 0, 0, nsnull, 0, &length);
245
    return NS_SUCCEEDED(rv) ? length : 0;
250
    return NS_SUCCEEDED(rv) ? length : 0;
246
  }
251
  }
247
252
248
  /**
253
  /**
249
   * Check if a line is reordered, i.e., if the child frames are not
254
   * Check if a line is reordered, i.e., if the child frames are not
250
   * all laid out left-to-right.
255
   * all laid out left-to-right.
251
   * @param aFirstFrameOnLine : first frame of the line to be tested
256
   * @param aFirstFrameOnLine : first frame of the line to be tested
252
   * @param aNumFramesOnLine : number of frames on this line
257
   * @param aNumFramesOnLine : number of frames on this line
253
   * @param[out] aLeftMost : leftmost frame on this line
258
   * @param[out] aLeftMost : leftmost frame on this line
254
   * @param[out] aRightMost : rightmost frame on this line
259
   * @param[out] aRightMost : rightmost frame on this line
255
   */
260
   */
256
  PRBool CheckLineOrder(nsIFrame*  aFirstFrameOnLine,
261
  static PRBool CheckLineOrder(nsIFrame*  aFirstFrameOnLine,
257
                        PRInt32    aNumFramesOnLine,
262
                               PRInt32    aNumFramesOnLine,
258
                        nsIFrame** aLeftmost,
263
                               nsIFrame** aLeftmost,
259
                        nsIFrame** aRightmost);
264
                               nsIFrame** aRightmost);
260
265
261
  /**
266
  /**
262
   * Get the frame to the right of the given frame, on the same line.
267
   * Get the frame to the right of the given frame, on the same line.
263
   * @param aFrame : We're looking for the frame to the right of this frame.
268
   * @param aFrame : We're looking for the frame to the right of this frame.
264
   *                 If null, return the leftmost frame on the line.
269
   *                 If null, return the leftmost frame on the line.
265
   * @param aFirstFrameOnLine : first frame of the line to be tested
270
   * @param aFirstFrameOnLine : first frame of the line to be tested
266
   * @param aNumFramesOnLine : number of frames on this line
271
   * @param aNumFramesOnLine : number of frames on this line
267
   */
272
   */
268
  nsIFrame* GetFrameToRightOf(const nsIFrame*  aFrame,
273
  static nsIFrame* GetFrameToRightOf(const nsIFrame*  aFrame,
269
                              nsIFrame*        aFirstFrameOnLine,
274
                                     nsIFrame*        aFirstFrameOnLine,
270
                              PRInt32          aNumFramesOnLine);
275
                                     PRInt32          aNumFramesOnLine);
271
    
276
    
272
  /**
277
  /**
273
   * Get the frame to the left of the given frame, on the same line.
278
   * Get the frame to the left of the given frame, on the same line.
274
   * @param aFrame : We're looking for the frame to the left of this frame.
279
   * @param aFrame : We're looking for the frame to the left of this frame.
275
   *                 If null, return the rightmost frame on the line.
280
   *                 If null, return the rightmost frame on the line.
276
   * @param aFirstFrameOnLine : first frame of the line to be tested
281
   * @param aFirstFrameOnLine : first frame of the line to be tested
277
   * @param aNumFramesOnLine : number of frames on this line
282
   * @param aNumFramesOnLine : number of frames on this line
278
   */
283
   */
279
  nsIFrame* GetFrameToLeftOf(const nsIFrame*  aFrame,
284
  static nsIFrame* GetFrameToLeftOf(const nsIFrame*  aFrame,
280
                             nsIFrame*        aFirstFrameOnLine,
285
                                    nsIFrame*        aFirstFrameOnLine,
281
                             PRInt32          aNumFramesOnLine);
286
                                    PRInt32          aNumFramesOnLine);
282
    
287
    
283
  /**
288
  /**
284
   * Get the bidi embedding level of the given (inline) frame.
289
   * Get the bidi embedding level of the given (inline) frame.
285
   */
290
   */
286
  static nsBidiLevel GetFrameEmbeddingLevel(nsIFrame* aFrame);
291
  static nsBidiLevel GetFrameEmbeddingLevel(nsIFrame* aFrame);
287
292
288
  /**
293
  /**
289
   * Get the bidi base level of the given (inline) frame.
294
   * Get the bidi base level of the given (inline) frame.
 Lines 307-479   public: Link Here 
307
   *  MODE_DRAW - invokes DrawText on the processor for each substring
312
   *  MODE_DRAW - invokes DrawText on the processor for each substring
308
   *  MODE_MEASURE - does not invoke DrawText on the processor
313
   *  MODE_MEASURE - does not invoke DrawText on the processor
309
   *  Note that the string is always measured, regardless of mode
314
   *  Note that the string is always measured, regardless of mode
310
   * @param[in,out] aPosResolve array of logical positions to resolve into
315
   * @param[in,out] aPosResolve array of logical positions to resolve into
311
   *  visual positions; can be nsnull if this functionality is not required
316
   *  visual positions; can be nsnull if this functionality is not required
312
   * @param aPosResolveCount number of items in the aPosResolve array
317
   * @param aPosResolveCount number of items in the aPosResolve array
313
   * @param[out] aWidth Pointer to where the width will be stored (may be null)
318
   * @param[out] aWidth Pointer to where the width will be stored (may be null)
314
   */
319
   */
315
  nsresult ProcessText(const PRUnichar*       aText,
320
  static nsresult ProcessText(const PRUnichar*       aText,
316
                       PRInt32                aLength,
321
                              PRInt32                aLength,
317
                       nsBidiDirection        aBaseDirection,
322
                              nsBidiDirection        aBaseDirection,
318
                       nsPresContext*         aPresContext,
323
                              nsPresContext*         aPresContext,
319
                       BidiProcessor&         aprocessor,
324
                              BidiProcessor&         aprocessor,
320
                       Mode                   aMode,
325
                              Mode                   aMode,
321
                       nsBidiPositionResolve* aPosResolve,
326
                              nsBidiPositionResolve* aPosResolve,
322
                       PRInt32                aPosResolveCount,
327
                              PRInt32                aPosResolveCount,
323
                       nscoord*               aWidth);
328
                              nscoord*               aWidth,
329
                              nsBidi*                aBidiEngine);
324
330
325
  /**
331
  /**
326
   * Make a copy of a string, converting from logical to visual order
332
   * Make a copy of a string, converting from logical to visual order
327
   *
333
   *
328
   * @param aSource the source string
334
   * @param aSource the source string
329
   * @param aDest the destination string
335
   * @param aDest the destination string
330
   * @param aBaseDirection the base direction of the string
336
   * @param aBaseDirection the base direction of the string
331
   *       (NSBIDI_LTR or NSBIDI_RTL to force the base direction;
337
   *       (NSBIDI_LTR or NSBIDI_RTL to force the base direction;
332
   *        NSBIDI_DEFAULT_LTR or NSBIDI_DEFAULT_RTL to let the bidi engine
338
   *        NSBIDI_DEFAULT_LTR or NSBIDI_DEFAULT_RTL to let the bidi engine
333
   *        determine the direction from rules P2 and P3 of the bidi algorithm.
339
   *        determine the direction from rules P2 and P3 of the bidi algorithm.
334
   *  @see nsBidi::GetPara
340
   *  @see nsBidi::GetPara
335
   * @param aOverride if TRUE, the text has a bidi override, according to
341
   * @param aOverride if TRUE, the text has a bidi override, according to
336
   *                    the direction in aDir
342
   *                    the direction in aDir
337
   */
343
   */
338
  void CopyLogicalToVisual(const nsAString& aSource,
344
  static void CopyLogicalToVisual(const nsAString& aSource,
339
                           nsAString& aDest,
345
                                  nsAString& aDest,
340
                           nsBidiLevel aBaseDirection,
346
                                  nsBidiLevel aBaseDirection,
341
                           PRBool aOverride);
347
                                  PRBool aOverride);
342
343
  /**
344
   * Guess at how much memory is being used by this nsBidiPresUtils instance,
345
   * including memory used by nsBidi.
346
   */
347
  PRUint32 EstimateMemoryUsed();
348
349
  void Traverse(nsCycleCollectionTraversalCallback &cb) const;
350
  void Unlink();
351
348
352
private:
349
private:
353
  nsresult ProcessTextForRenderingContext(const PRUnichar*       aText,
350
  static nsresult ProcessTextForRenderingContext(const PRUnichar*       aText,
354
                                          PRInt32                aLength,
351
                                                 PRInt32                aLength,
355
                                          nsBidiDirection        aBaseDirection,
352
                                                 nsBidiDirection        aBaseDirection,
356
                                          nsPresContext*         aPresContext,
353
                                                 nsPresContext*         aPresContext,
357
                                          nsIRenderingContext&   aRenderingContext,
354
                                                 nsIRenderingContext&   aRenderingContext,
358
                                          nsIRenderingContext&   aTextRunConstructionContext,
355
                                                 nsIRenderingContext&   aTextRunConstructionContext,
359
                                          Mode                   aMode,
356
                                                 Mode                   aMode,
360
                                          nscoord                aX, // DRAW only
357
                                                 nscoord                aX, // DRAW only
361
                                          nscoord                aY, // DRAW only
358
                                                 nscoord                aY, // DRAW only
362
                                          nsBidiPositionResolve* aPosResolve,  /* may be null */
359
                                                 nsBidiPositionResolve* aPosResolve,  /* may be null */
363
                                          PRInt32                aPosResolveCount,
360
                                                 PRInt32                aPosResolveCount,
364
                                          nscoord*               aWidth /* may be null */);
361
                                                 nscoord*               aWidth /* may be null */);
365
362
366
  /**
363
  /**
367
   * Traverse the child frames of the block element and:
364
   * Traverse the child frames of the block element and:
368
   *  Set up an array of the frames in logical order
365
   *  Set up an array of the frames in logical order
369
   *  Create a string containing the text content of all the frames
366
   *  Create a string containing the text content of all the frames
370
   *  If we encounter content that requires us to split the element into more
367
   *  If we encounter content that requires us to split the element into more
371
   *  than one paragraph for bidi resolution, resolve the paragraph up to that
368
   *  than one paragraph for bidi resolution, resolve the paragraph up to that
372
   *  point.
369
   *  point.
373
   */
370
   */
374
  void TraverseFrames(nsBlockFrame* aBlockFrame, nsIFrame* aCurrentFrame);
371
  static void TraverseFrames(nsBlockFrame* aBlockFrame, nsIFrame* aCurrentFrame,
375
372
                            BidiParagraphData *aBpd);
376
  /**
377
   * Initialize the logically-ordered array of frames
378
   * using the top-level frames of a single line
379
   */
380
  void InitLogicalArrayFromLine(nsIFrame* aFirstFrameOnLine,
381
                                PRInt32   aNumFramesOnLine);
382
383
  /**
384
   * Reorder the frame array from logical to visual order
385
   * 
386
   * @param aReordered TRUE on return if the visual order is different from
387
   *                   the logical order
388
   * @param aHasRTLFrames TRUE on return if at least one of the frames is RTL
389
   *                      (and therefore might have reordered descendents)
390
   */
391
  nsresult Reorder(PRBool& aReordered, PRBool& aHasRTLFrames);
392
  
373
  
393
  /*
374
  /*
394
   * Position aFrame and it's descendants to their visual places. Also if aFrame
375
   * Position aFrame and it's descendants to their visual places. Also if aFrame
395
   * is not leaf, resize it to embrace it's children.
376
   * is not leaf, resize it to embrace it's children.
396
   *
377
   *
397
   * @param aFrame               The frame which itself and its children are going
378
   * @param aFrame               The frame which itself and its children are going
398
   *                             to be repositioned
379
   *                             to be repositioned
399
   * @param aIsOddLevel          TRUE means the embedding level of this frame is odd
380
   * @param aIsOddLevel          TRUE means the embedding level of this frame is odd
400
   * @param[in,out] aLeft        IN value is the starting position of aFrame(without
381
   * @param[in,out] aLeft        IN value is the starting position of aFrame(without
401
   *                             considering its left margin)
382
   *                             considering its left margin)
402
   *                             OUT value will be the ending position of aFrame(after
383
   *                             OUT value will be the ending position of aFrame(after
403
   *                             adding its right margin)
384
   *                             adding its right margin)
404
   * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
385
   * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
405
   */
386
   */
406
  void RepositionFrame(nsIFrame*              aFrame,
387
  static void RepositionFrame(nsIFrame*              aFrame,
407
                       PRBool                 aIsOddLevel,
388
                              PRBool                 aIsOddLevel,
408
                       nscoord&               aLeft,
389
                              nscoord&               aLeft,
409
                       nsContinuationStates*  aContinuationStates) const;
390
                              nsContinuationStates*  aContinuationStates);
410
391
411
  /*
392
  /*
412
   * Initialize the continuation state(nsFrameContinuationState) to
393
   * Initialize the continuation state(nsFrameContinuationState) to
413
   * (nsnull, 0) for aFrame and its descendants.
394
   * (nsnull, 0) for aFrame and its descendants.
414
   *
395
   *
415
   * @param aFrame               The frame which itself and its descendants will
396
   * @param aFrame               The frame which itself and its descendants will
416
   *                             be initialized
397
   *                             be initialized
417
   * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
398
   * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
418
   */
399
   */
419
  void InitContinuationStates(nsIFrame*              aFrame,
400
  static void InitContinuationStates(nsIFrame*              aFrame,
420
                              nsContinuationStates*  aContinuationStates) const;
401
                                     nsContinuationStates*  aContinuationStates);
421
402
422
  /*
403
  /*
423
   * Determine if aFrame is leftmost or rightmost, and set aIsLeftMost and
404
   * Determine if aFrame is leftmost or rightmost, and set aIsLeftMost and
424
   * aIsRightMost values. Also set continuation states of aContinuationStates.
405
   * aIsRightMost values. Also set continuation states of aContinuationStates.
425
   *
406
   *
426
   * A frame is leftmost if it's the first appearance of its continuation chain
407
   * A frame is leftmost if it's the first appearance of its continuation chain
427
   * on the line and the chain is on its first line if it's LTR or the chain is
408
   * on the line and the chain is on its first line if it's LTR or the chain is
428
   * on its last line if it's RTL.
409
   * on its last line if it's RTL.
429
   * A frame is rightmost if it's the last appearance of its continuation chain
410
   * A frame is rightmost if it's the last appearance of its continuation chain
430
   * on the line and the chain is on its first line if it's RTL or the chain is
411
   * on the line and the chain is on its first line if it's RTL or the chain is
431
   * on its last line if it's LTR.
412
   * on its last line if it's LTR.
432
   *
413
   *
433
   * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
414
   * @param aContinuationStates  A map from nsIFrame* to nsFrameContinuationState
434
   * @param[out] aIsLeftMost     TRUE means aFrame is leftmost frame or continuation
415
   * @param[out] aIsLeftMost     TRUE means aFrame is leftmost frame or continuation
435
   * @param[out] aIsRightMost    TRUE means aFrame is rightmost frame or continuation
416
   * @param[out] aIsRightMost    TRUE means aFrame is rightmost frame or continuation
436
   */
417
   */
437
   void IsLeftOrRightMost(nsIFrame*              aFrame,
418
   static void IsLeftOrRightMost(nsIFrame*              aFrame,
438
                          nsContinuationStates*  aContinuationStates,
419
                                 nsContinuationStates*  aContinuationStates,
439
                          PRBool&                aIsLeftMost /* out */,
420
                                 PRBool&                aIsLeftMost /* out */,
440
                          PRBool&                aIsRightMost /* out */) const;
421
                                 PRBool&                aIsRightMost /* out */);
441
422
442
  /**
423
  /**
443
   *  Adjust frame positions following their visual order
424
   *  Adjust frame positions following their visual order
444
   *
425
   *
445
   *  @param aFirstChild the first kid
426
   *  @param aFirstChild the first kid
446
   *
427
   *
447
   *  @lina 04/11/2000
428
   *  @lina 04/11/2000
448
   */
429
   */
449
  void RepositionInlineFrames(nsIFrame* aFirstChild) const;
430
  static void RepositionInlineFrames(BidiLineData *aBld,
431
                                     nsIFrame* aFirstChild);
450
  
432
  
451
  /**
433
  /**
452
   * Helper method for Resolve()
434
   * Helper method for Resolve()
453
   * Truncate a text frame to the end of a single-directional run and possibly
435
   * Truncate a text frame to the end of a single-directional run and possibly
454
   * create a continuation frame for the remainder of its content.
436
   * create a continuation frame for the remainder of its content.
455
   *
437
   *
456
   * @param aFrame       the original frame
438
   * @param aFrame       the original frame
457
   * @param aNewFrame    [OUT] the new frame that was created
439
   * @param aNewFrame    [OUT] the new frame that was created
458
   * @param aFrameIndex  [IN/OUT] index of aFrame in mLogicalFrames
440
   * @param aFrameIndex  [IN/OUT] index of aFrame in mLogicalFrames
459
   * @param aStart       [IN] the start of the content mapped by aFrame (and 
441
   * @param aStart       [IN] the start of the content mapped by aFrame (and 
460
   *                          any fluid continuations)
442
   *                          any fluid continuations)
461
   * @param aEnd         [IN] the offset of the end of the single-directional
443
   * @param aEnd         [IN] the offset of the end of the single-directional
462
   *                          text run.
444
   *                          text run.
463
   * @see Resolve()
445
   * @see Resolve()
464
   * @see RemoveBidiContinuation()
446
   * @see RemoveBidiContinuation()
465
   */
447
   */
466
  inline
448
  static inline
467
  void EnsureBidiContinuation(nsIFrame*       aFrame,
449
  nsresult EnsureBidiContinuation(nsIFrame*       aFrame,
468
                              nsIFrame**      aNewFrame,
450
                                  nsIFrame**      aNewFrame,
469
                              PRInt32&        aFrameIndex,
451
                                  PRInt32&        aFrameIndex,
470
                              PRInt32         aStart,
452
                                  PRInt32         aStart,
471
                              PRInt32         aEnd);
453
                                  PRInt32         aEnd);
472
454
473
  /**
455
  /**
474
   * Helper method for Resolve()
456
   * Helper method for Resolve()
475
   * Convert one or more bidi continuation frames created in a previous reflow by
457
   * Convert one or more bidi continuation frames created in a previous reflow by
476
   * EnsureBidiContinuation() into fluid continuations.
458
   * EnsureBidiContinuation() into fluid continuations.
477
   * @param aFrame       the frame whose continuations are to be removed
459
   * @param aFrame       the frame whose continuations are to be removed
478
   * @param aFirstIndex  index of aFrame in mLogicalFrames
460
   * @param aFirstIndex  index of aFrame in mLogicalFrames
479
   * @param aLastIndex   index of the last frame to be removed
461
   * @param aLastIndex   index of the last frame to be removed
 Lines 481-534   private: Link Here 
481
   *                     directional frames have control characters
463
   *                     directional frames have control characters
482
   *                     corresponding to them in mBuffer, the pointers to
464
   *                     corresponding to them in mBuffer, the pointers to
483
   *                     mBuffer in Resolve() will need to be updated after
465
   *                     mBuffer in Resolve() will need to be updated after
484
   *                     deleting the frames.
466
   *                     deleting the frames.
485
   *
467
   *
486
   * @see Resolve()
468
   * @see Resolve()
487
   * @see EnsureBidiContinuation()
469
   * @see EnsureBidiContinuation()
488
   */
470
   */
489
  void RemoveBidiContinuation(nsIFrame*       aFrame,
471
  static void RemoveBidiContinuation(BidiParagraphData* aBpd,
490
                              PRInt32         aFirstIndex,
472
                                     nsIFrame*       aFrame,
491
                              PRInt32         aLastIndex,
473
                                     PRInt32         aFirstIndex,
492
                              PRInt32&        aOffset) const;
474
                                     PRInt32         aLastIndex,
493
  void CalculateCharType(PRInt32& aOffset,
475
                                     PRInt32&        aOffset);
494
                         PRInt32  aCharTypeLimit,
476
  static void CalculateCharType(nsBidi* aBidiEngine,
495
                         PRInt32& aRunLimit,
477
                                const PRUnichar* aText,
496
                         PRInt32& aRunLength,
478
                                PRInt32& aOffset,
497
                         PRInt32& aRunCount,
479
                                PRInt32  aCharTypeLimit,
498
                         PRUint8& aCharType,
480
                                PRInt32& aRunLimit,
499
                         PRUint8& aPrevCharType) const;
481
                                PRInt32& aRunLength,
482
                                PRInt32& aRunCount,
483
                                PRUint8& aCharType,
484
                                PRUint8& aPrevCharType);
500
  
485
  
501
  void StripBidiControlCharacters(PRUnichar* aText,
486
  static void StripBidiControlCharacters(PRUnichar* aText,
502
                                  PRInt32&   aTextLength) const;
487
                                         PRInt32&   aTextLength);
503
488
504
  static PRBool WriteLogicalToVisual(const PRUnichar* aSrc,
489
  static PRBool WriteLogicalToVisual(const PRUnichar* aSrc,
505
                                     PRUint32 aSrcLength,
490
                                     PRUint32 aSrcLength,
506
                                     PRUnichar* aDest,
491
                                     PRUnichar* aDest,
507
                                     nsBidiLevel aBaseDirection,
492
                                     nsBidiLevel aBaseDirection,
508
                                     nsBidi* aBidiEngine);
493
                                     nsBidi* aBidiEngine);
509
494
510
 static void WriteReverse(const PRUnichar* aSrc,
495
  static void WriteReverse(const PRUnichar* aSrc,
511
                          PRUint32 aSrcLength,
496
                           PRUint32 aSrcLength,
512
                          PRUnichar* aDest);
497
                           PRUnichar* aDest);
513
514
  nsString        mBuffer;
515
  nsTArray<PRUnichar> mEmbeddingStack;
516
  nsTArray<nsIFrame*> mLogicalFrames;
517
  nsTArray<nsIFrame*> mVisualFrames;
518
  nsDataHashtable<nsISupportsHashKey, PRInt32> mContentToFrameIndex;
519
  PRInt32         mArraySize;
520
  PRInt32*        mIndexMap;
521
  PRUint8*        mLevels;
522
  nsresult        mSuccess;
523
  PRPackedBool    mIsVisual;
524
  nsBidiLevel     mParaLevel;
525
  nsIFrame*       mPrevFrame;
526
  nsIContent*     mPrevContent;
527
528
  nsAutoPtr<nsBlockInFlowLineIterator> mLineIter;
529
  nsBidi*         mBidiEngine;
530
};
498
};
531
499
532
#endif /* nsBidiPresUtils_h___ */
500
#endif /* nsBidiPresUtils_h___ */
533
501
534
#endif // IBMBIDI
502
#endif // IBMBIDI
(-)a/layout/base/nsLayoutUtils.cpp (-22 / +14 lines)
Line     Link Here 
 Lines 2763-2791   nsLayoutUtils::DrawString(const nsIFrame Link Here 
2763
                          PRInt32              aLength,
2763
                          PRInt32              aLength,
2764
                          nsPoint              aPoint,
2764
                          nsPoint              aPoint,
2765
                          PRUint8              aDirection)
2765
                          PRUint8              aDirection)
2766
{
2766
{
2767
#ifdef IBMBIDI
2767
#ifdef IBMBIDI
2768
  nsresult rv = NS_ERROR_FAILURE;
2768
  nsresult rv = NS_ERROR_FAILURE;
2769
  nsPresContext* presContext = aFrame->PresContext();
2769
  nsPresContext* presContext = aFrame->PresContext();
2770
  if (presContext->BidiEnabled()) {
2770
  if (presContext->BidiEnabled()) {
2771
    nsBidiPresUtils* bidiUtils = presContext->GetBidiUtils();
2771
    if (aDirection == NS_STYLE_DIRECTION_INHERIT) {
2772
2772
      aDirection = aFrame->GetStyleVisibility()->mDirection;
2773
    if (bidiUtils) {
2774
      if (aDirection == NS_STYLE_DIRECTION_INHERIT) {
2775
        aDirection = aFrame->GetStyleVisibility()->mDirection;
2776
      }
2777
      nsBidiDirection direction =
2778
        (NS_STYLE_DIRECTION_RTL == aDirection) ?
2779
        NSBIDI_RTL : NSBIDI_LTR;
2780
      rv = bidiUtils->RenderText(aString, aLength, direction,
2781
                                 presContext, *aContext, *aContext,
2782
                                 aPoint.x, aPoint.y);
2783
    }
2773
    }
2774
    nsBidiDirection direction =
2775
      (NS_STYLE_DIRECTION_RTL == aDirection) ?
2776
      NSBIDI_RTL : NSBIDI_LTR;
2777
    rv = nsBidiPresUtils::RenderText(aString, aLength, direction,
2778
                                     presContext, *aContext, *aContext,
2779
                                     aPoint.x, aPoint.y);
2784
  }
2780
  }
2785
  if (NS_FAILED(rv))
2781
  if (NS_FAILED(rv))
2786
#endif // IBMBIDI
2782
#endif // IBMBIDI
2787
  {
2783
  {
2788
    aContext->SetTextRunRTL(PR_FALSE);
2784
    aContext->SetTextRunRTL(PR_FALSE);
2789
    aContext->DrawString(aString, aLength, aPoint.x, aPoint.y);
2785
    aContext->DrawString(aString, aLength, aPoint.x, aPoint.y);
2790
  }
2786
  }
2791
}
2787
}
 Lines 2794-2819   nscoord Link Here 
2794
nsLayoutUtils::GetStringWidth(const nsIFrame*      aFrame,
2790
nsLayoutUtils::GetStringWidth(const nsIFrame*      aFrame,
2795
                              nsIRenderingContext* aContext,
2791
                              nsIRenderingContext* aContext,
2796
                              const PRUnichar*     aString,
2792
                              const PRUnichar*     aString,
2797
                              PRInt32              aLength)
2793
                              PRInt32              aLength)
2798
{
2794
{
2799
#ifdef IBMBIDI
2795
#ifdef IBMBIDI
2800
  nsPresContext* presContext = aFrame->PresContext();
2796
  nsPresContext* presContext = aFrame->PresContext();
2801
  if (presContext->BidiEnabled()) {
2797
  if (presContext->BidiEnabled()) {
2802
    nsBidiPresUtils* bidiUtils = presContext->GetBidiUtils();
2798
    const nsStyleVisibility* vis = aFrame->GetStyleVisibility();
2803
2799
    nsBidiDirection direction =
2804
    if (bidiUtils) {
2800
      (NS_STYLE_DIRECTION_RTL == vis->mDirection) ?
2805
      const nsStyleVisibility* vis = aFrame->GetStyleVisibility();
2801
      NSBIDI_RTL : NSBIDI_LTR;
2806
      nsBidiDirection direction =
2802
    return nsBidiPresUtils::MeasureTextWidth(aString, aLength,
2807
        (NS_STYLE_DIRECTION_RTL == vis->mDirection) ?
2803
                                             direction, presContext, *aContext);
2808
        NSBIDI_RTL : NSBIDI_LTR;
2809
      return bidiUtils->MeasureTextWidth(aString, aLength,
2810
                                         direction, presContext, *aContext);
2811
    }
2812
  }
2804
  }
2813
#endif // IBMBIDI
2805
#endif // IBMBIDI
2814
  aContext->SetTextRunRTL(PR_FALSE);
2806
  aContext->SetTextRunRTL(PR_FALSE);
2815
  nscoord width;
2807
  nscoord width;
2816
  aContext->GetWidth(aString, aLength, width);
2808
  aContext->GetWidth(aString, aLength, width);
2817
  return width;
2809
  return width;
2818
}
2810
}
2819
2811
(-)a/layout/base/nsPresContext.cpp (-22 lines)
Line     Link Here 
 Lines 353-370   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN( Link Here 
353
353
354
  for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
354
  for (PRUint32 i = 0; i < IMAGE_LOAD_TYPE_COUNT; ++i)
355
    tmp->mImageLoaders[i].Enumerate(TraverseImageLoader, &cb);
355
    tmp->mImageLoaders[i].Enumerate(TraverseImageLoader, &cb);
356
356
357
  // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTheme); // a service
357
  // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTheme); // a service
358
  // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLangService); // a service
358
  // NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mLangService); // a service
359
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrintSettings);
359
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrintSettings);
360
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrefChangedTimer);
360
  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrefChangedTimer);
361
  if (tmp->mBidiUtils)
362
    tmp->mBidiUtils->Traverse(cb);
363
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
361
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
364
362
365
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPresContext)
363
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsPresContext)
366
  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument);
364
  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument);
367
  NS_RELEASE(tmp->mDeviceContext); // worth bothering?
365
  NS_RELEASE(tmp->mDeviceContext); // worth bothering?
368
  if (tmp->mEventManager) {
366
  if (tmp->mEventManager) {
369
    // unclear if these are needed, but can't hurt
367
    // unclear if these are needed, but can't hurt
370
    tmp->mEventManager->NotifyDestroyPresContext(tmp);
368
    tmp->mEventManager->NotifyDestroyPresContext(tmp);
 Lines 379-396   NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns Link Here 
379
  // NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTheme); // a service
377
  // NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mTheme); // a service
380
  // NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLangService); // a service
378
  // NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mLangService); // a service
381
  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrintSettings);
379
  NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrintSettings);
382
  if (tmp->mPrefChangedTimer)
380
  if (tmp->mPrefChangedTimer)
383
  {
381
  {
384
    tmp->mPrefChangedTimer->Cancel();
382
    tmp->mPrefChangedTimer->Cancel();
385
    tmp->mPrefChangedTimer = nsnull;
383
    tmp->mPrefChangedTimer = nsnull;
386
  }
384
  }
387
  if (tmp->mBidiUtils)
388
    tmp->mBidiUtils->Unlink();
389
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
385
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
390
386
391
387
392
#define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
388
#define MAKE_FONT_PREF_KEY(_pref, _s0, _s1) \
393
 _pref.Assign(_s0); \
389
 _pref.Assign(_s0); \
394
 _pref.Append(_s1);
390
 _pref.Append(_s1);
395
391
396
static const char* const kGenericFont[] = {
392
static const char* const kGenericFont[] = {
 Lines 1432-1456   nsPresContext::SetBidiEnabled() const Link Here 
1432
  if (mShell) {
1428
  if (mShell) {
1433
    nsIDocument *doc = mShell->GetDocument();
1429
    nsIDocument *doc = mShell->GetDocument();
1434
    if (doc) {
1430
    if (doc) {
1435
      doc->SetBidiEnabled();
1431
      doc->SetBidiEnabled();
1436
    }
1432
    }
1437
  }
1433
  }
1438
}
1434
}
1439
1435
1440
nsBidiPresUtils*
1441
nsPresContext::GetBidiUtils()
1442
{
1443
  if (!mBidiUtils)
1444
    mBidiUtils = new nsBidiPresUtils;
1445
1446
  return mBidiUtils;
1447
}
1448
1449
void
1436
void
1450
nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceRestyle)
1437
nsPresContext::SetBidi(PRUint32 aSource, PRBool aForceRestyle)
1451
{
1438
{
1452
  // Don't do all this stuff unless the options have changed.
1439
  // Don't do all this stuff unless the options have changed.
1453
  if (aSource == GetBidi()) {
1440
  if (aSource == GetBidi()) {
1454
    return;
1441
    return;
1455
  }
1442
  }
1456
1443
 Lines 1483-1507   nsPresContext::SetBidi(PRUint32 aSource, Link Here 
1483
}
1470
}
1484
1471
1485
PRUint32
1472
PRUint32
1486
nsPresContext::GetBidi() const
1473
nsPresContext::GetBidi() const
1487
{
1474
{
1488
  return Document()->GetBidiOptions();
1475
  return Document()->GetBidiOptions();
1489
}
1476
}
1490
1477
1491
PRUint32
1492
nsPresContext::GetBidiMemoryUsed()
1493
{
1494
  if (!mBidiUtils)
1495
    return 0;
1496
1497
  return mBidiUtils->EstimateMemoryUsed();
1498
}
1499
1500
#endif //IBMBIDI
1478
#endif //IBMBIDI
1501
1479
1502
PRBool
1480
PRBool
1503
nsPresContext::IsTopLevelWindowInactive()
1481
nsPresContext::IsTopLevelWindowInactive()
1504
{
1482
{
1505
  nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryReferent(mContainer));
1483
  nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryReferent(mContainer));
1506
  if (!treeItem)
1484
  if (!treeItem)
1507
    return PR_FALSE;
1485
    return PR_FALSE;
(-)a/layout/base/nsPresContext.h (-14 lines)
Line     Link Here 
 Lines 742-777   public: Link Here 
742
   *
742
   *
743
   *  @lina 05/02/2000
743
   *  @lina 05/02/2000
744
   */
744
   */
745
  PRBool IsVisualMode() const { return mIsVisual; }
745
  PRBool IsVisualMode() const { return mIsVisual; }
746
746
747
//Mohamed
747
//Mohamed
748
748
749
  /**
749
  /**
750
   * Get a Bidi presentation utilities object
751
   */
752
  NS_HIDDEN_(nsBidiPresUtils*) GetBidiUtils();
753
754
  /**
755
   * Set the Bidi options for the presentation context
750
   * Set the Bidi options for the presentation context
756
   */  
751
   */  
757
  NS_HIDDEN_(void) SetBidi(PRUint32 aBidiOptions,
752
  NS_HIDDEN_(void) SetBidi(PRUint32 aBidiOptions,
758
                           PRBool aForceRestyle = PR_FALSE);
753
                           PRBool aForceRestyle = PR_FALSE);
759
754
760
  /**
755
  /**
761
   * Get the Bidi options for the presentation context
756
   * Get the Bidi options for the presentation context
762
   * Not inline so consumers of nsPresContext are not forced to
757
   * Not inline so consumers of nsPresContext are not forced to
763
   * include nsIDocument.
758
   * include nsIDocument.
764
   */  
759
   */  
765
  NS_HIDDEN_(PRUint32) GetBidi() const;
760
  NS_HIDDEN_(PRUint32) GetBidi() const;
766
767
  PRUint32 GetBidiMemoryUsed();
768
#else
769
  PRUint32 GetBidiMemoryUsed() { return 0; }
770
#endif // IBMBIDI
761
#endif // IBMBIDI
771
762
772
  /**
763
  /**
773
   * Render only Selection
764
   * Render only Selection
774
   */
765
   */
775
  void SetIsRenderingOnlySelection(PRBool aResult)
766
  void SetIsRenderingOnlySelection(PRBool aResult)
776
  {
767
  {
777
    NS_ASSERTION(!(aResult & ~1), "Value must be true or false");
768
    NS_ASSERTION(!(aResult & ~1), "Value must be true or false");
 Lines 989-1005   public: Link Here 
989
980
990
  PRBool MayHaveFixedBackgroundFrames() { return mMayHaveFixedBackgroundFrames; }
981
  PRBool MayHaveFixedBackgroundFrames() { return mMayHaveFixedBackgroundFrames; }
991
  void SetHasFixedBackgroundFrame() { mMayHaveFixedBackgroundFrames = PR_TRUE; }
982
  void SetHasFixedBackgroundFrame() { mMayHaveFixedBackgroundFrames = PR_TRUE; }
992
983
993
  PRUint32 EstimateMemoryUsed() {
984
  PRUint32 EstimateMemoryUsed() {
994
    PRUint32 result = 0;
985
    PRUint32 result = 0;
995
986
996
    result += sizeof(nsPresContext);
987
    result += sizeof(nsPresContext);
997
    result += GetBidiMemoryUsed();
998
988
999
    return result;
989
    return result;
1000
  }
990
  }
1001
991
1002
  PRBool IsRootContentDocument();
992
  PRBool IsRootContentDocument();
1003
993
1004
protected:
994
protected:
1005
  friend class nsRunnableMethod<nsPresContext>;
995
  friend class nsRunnableMethod<nsPresContext>;
 Lines 1073-1092   protected: Link Here 
1073
1063
1074
  PRInt32               mMinFontSize;   // Min font size, defaults to 0
1064
  PRInt32               mMinFontSize;   // Min font size, defaults to 0
1075
  float                 mTextZoom;      // Text zoom, defaults to 1.0
1065
  float                 mTextZoom;      // Text zoom, defaults to 1.0
1076
  float                 mFullZoom;      // Page zoom, defaults to 1.0
1066
  float                 mFullZoom;      // Page zoom, defaults to 1.0
1077
1067
1078
  PRInt32               mCurAppUnitsPerDevPixel;
1068
  PRInt32               mCurAppUnitsPerDevPixel;
1079
  PRInt32               mAutoQualityMinFontSizePixelsPref;
1069
  PRInt32               mAutoQualityMinFontSizePixelsPref;
1080
1070
1081
#ifdef IBMBIDI
1082
  nsAutoPtr<nsBidiPresUtils> mBidiUtils;
1083
#endif
1084
1085
  nsCOMPtr<nsITheme> mTheme;
1071
  nsCOMPtr<nsITheme> mTheme;
1086
  nsCOMPtr<nsILanguageAtomService> mLangService;
1072
  nsCOMPtr<nsILanguageAtomService> mLangService;
1087
  nsCOMPtr<nsIPrintSettings> mPrintSettings;
1073
  nsCOMPtr<nsIPrintSettings> mPrintSettings;
1088
  nsCOMPtr<nsITimer>    mPrefChangedTimer;
1074
  nsCOMPtr<nsITimer>    mPrefChangedTimer;
1089
1075
1090
  FramePropertyTable    mPropertyTable;
1076
  FramePropertyTable    mPropertyTable;
1091
1077
1092
  nsInvalidateRequestList mInvalidateRequests;
1078
  nsInvalidateRequestList mInvalidateRequests;
(-)a/layout/base/nsPresShell.cpp (-20 lines)
Line     Link Here 
 Lines 1411-1452   public: Link Here 
1411
  {
1411
  {
1412
    PresShell *aShell = static_cast<PresShell*>(aEntry->GetKey());
1412
    PresShell *aShell = static_cast<PresShell*>(aEntry->GetKey());
1413
    PRUint32 *val = (PRUint32*)userArg;
1413
    PRUint32 *val = (PRUint32*)userArg;
1414
    *val += aShell->EstimateMemoryUsed();
1414
    *val += aShell->EstimateMemoryUsed();
1415
    *val += aShell->mPresContext->EstimateMemoryUsed();
1415
    *val += aShell->mPresContext->EstimateMemoryUsed();
1416
    return PL_DHASH_NEXT;
1416
    return PL_DHASH_NEXT;
1417
  }
1417
  }
1418
1418
1419
  static PLDHashOperator LiveShellBidiSizeEnumerator(PresShellPtrKey *aEntry,
1420
                                                     void *userArg)
1421
  {
1422
    PresShell *aShell = static_cast<PresShell*>(aEntry->GetKey());
1423
    PRUint32 *val = (PRUint32*)userArg;
1424
    *val += aShell->mPresContext->GetBidiMemoryUsed();
1425
    return PL_DHASH_NEXT;
1426
  }
1427
1428
  static PRUint32
1419
  static PRUint32
1429
  EstimateShellsMemory(nsTHashtable<PresShellPtrKey>::Enumerator aEnumerator)
1420
  EstimateShellsMemory(nsTHashtable<PresShellPtrKey>::Enumerator aEnumerator)
1430
  {
1421
  {
1431
    PRUint32 result = 0;
1422
    PRUint32 result = 0;
1432
    sLiveShells->EnumerateEntries(aEnumerator, &result);
1423
    sLiveShells->EnumerateEntries(aEnumerator, &result);
1433
    return result;
1424
    return result;
1434
  }
1425
  }
1435
                  
1426
                  
1436
                                  
1427
                                  
1437
  static PRInt64 SizeOfLayoutMemoryReporter(void *) {
1428
  static PRInt64 SizeOfLayoutMemoryReporter(void *) {
1438
    return EstimateShellsMemory(LiveShellSizeEnumerator);
1429
    return EstimateShellsMemory(LiveShellSizeEnumerator);
1439
  }
1430
  }
1440
1431
1441
  static PRInt64 SizeOfBidiMemoryReporter(void *) {
1442
    return EstimateShellsMemory(LiveShellBidiSizeEnumerator);
1443
  }
1444
1445
protected:
1432
protected:
1446
  void QueryIsActive();
1433
  void QueryIsActive();
1447
  nsresult UpdateImageLockingState();
1434
  nsresult UpdateImageLockingState();
1448
};
1435
};
1449
1436
1450
class nsAutoCauseReflowNotifier
1437
class nsAutoCauseReflowNotifier
1451
{
1438
{
1452
public:
1439
public:
 Lines 1652-1673   NS_NewPresShell(nsIPresShell** aInstance Link Here 
1652
nsTHashtable<PresShell::PresShellPtrKey> *nsIPresShell::sLiveShells = 0;
1639
nsTHashtable<PresShell::PresShellPtrKey> *nsIPresShell::sLiveShells = 0;
1653
1640
1654
NS_MEMORY_REPORTER_IMPLEMENT(LayoutPresShell,
1641
NS_MEMORY_REPORTER_IMPLEMENT(LayoutPresShell,
1655
                             "layout/all",
1642
                             "layout/all",
1656
                             "Memory in use by layout PresShell, PresContext, and other related areas.",
1643
                             "Memory in use by layout PresShell, PresContext, and other related areas.",
1657
                             PresShell::SizeOfLayoutMemoryReporter,
1644
                             PresShell::SizeOfLayoutMemoryReporter,
1658
                             nsnull)
1645
                             nsnull)
1659
1646
1660
NS_MEMORY_REPORTER_IMPLEMENT(LayoutBidi,
1661
                             "layout/bidi",
1662
                             "Memory in use by layout Bidi processor.",
1663
                             PresShell::SizeOfBidiMemoryReporter,
1664
                             nsnull)
1665
1666
PresShell::PresShell()
1647
PresShell::PresShell()
1667
{
1648
{
1668
  mSelection = nsnull;
1649
  mSelection = nsnull;
1669
#ifdef MOZ_REFLOW_PERF
1650
#ifdef MOZ_REFLOW_PERF
1670
  mReflowCountMgr = new ReflowCountMgr();
1651
  mReflowCountMgr = new ReflowCountMgr();
1671
  mReflowCountMgr->SetPresContext(mPresContext);
1652
  mReflowCountMgr->SetPresContext(mPresContext);
1672
  mReflowCountMgr->SetPresShell(this);
1653
  mReflowCountMgr->SetPresShell(this);
1673
#endif
1654
#endif
 Lines 1685-1701   PresShell::PresShell() Link Here 
1685
  mRenderFlags = 0;
1666
  mRenderFlags = 0;
1686
  mXResolution = 1.0;
1667
  mXResolution = 1.0;
1687
  mYResolution = 1.0;
1668
  mYResolution = 1.0;
1688
  mViewportOverridden = PR_FALSE;
1669
  mViewportOverridden = PR_FALSE;
1689
1670
1690
  static bool registeredReporter = false;
1671
  static bool registeredReporter = false;
1691
  if (!registeredReporter) {
1672
  if (!registeredReporter) {
1692
    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(LayoutPresShell));
1673
    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(LayoutPresShell));
1693
    NS_RegisterMemoryReporter(new NS_MEMORY_REPORTER_NAME(LayoutBidi));
1694
    registeredReporter = true;
1674
    registeredReporter = true;
1695
  }
1675
  }
1696
1676
1697
  new (this) nsFrameManager();
1677
  new (this) nsFrameManager();
1698
1678
1699
  sLiveShells->PutEntry(this);
1679
  sLiveShells->PutEntry(this);
1700
}
1680
}
1701
1681
(-)a/layout/generic/nsBlockFrame.cpp (-10 / +2 lines)
Line     Link Here 
 Lines 4234-4254   nsBlockFrame::PlaceLine(nsBlockReflowSta Link Here 
4234
  // RelativePositionFrames!!!
4234
  // RelativePositionFrames!!!
4235
  // XXXldb Is something here considering relatively positioned frames at
4235
  // XXXldb Is something here considering relatively positioned frames at
4236
  // other than their original positions?
4236
  // other than their original positions?
4237
#ifdef IBMBIDI
4237
#ifdef IBMBIDI
4238
  // XXXldb Why don't we do this earlier?
4238
  // XXXldb Why don't we do this earlier?
4239
  if (aState.mPresContext->BidiEnabled()) {
4239
  if (aState.mPresContext->BidiEnabled()) {
4240
    if (!aState.mPresContext->IsVisualMode() ||
4240
    if (!aState.mPresContext->IsVisualMode() ||
4241
        GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
4241
        GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
4242
      nsBidiPresUtils* bidiUtils = aState.mPresContext->GetBidiUtils();
4242
      nsBidiPresUtils::ReorderFrames(aLine->mFirstChild, aLine->GetChildCount());
4243
4244
      if (bidiUtils && bidiUtils->IsSuccessful() ) {
4245
        bidiUtils->ReorderFrames(aLine->mFirstChild, aLine->GetChildCount());
4246
      } // bidiUtils
4247
    } // not visual mode
4243
    } // not visual mode
4248
  } // bidi enabled
4244
  } // bidi enabled
4249
#endif // IBMBIDI
4245
#endif // IBMBIDI
4250
4246
4251
  // From here on, pfd->mBounds rectangles are incorrect because bidi
4247
  // From here on, pfd->mBounds rectangles are incorrect because bidi
4252
  // might have moved frames around!
4248
  // might have moved frames around!
4253
  nsOverflowAreas overflowAreas;
4249
  nsOverflowAreas overflowAreas;
4254
  aLineLayout.RelativePositionFrames(overflowAreas);
4250
  aLineLayout.RelativePositionFrames(overflowAreas);
 Lines 7161-7181   nsBlockFrame::ResolveBidi() Link Here 
7161
  NS_ASSERTION(!GetPrevInFlow(),
7157
  NS_ASSERTION(!GetPrevInFlow(),
7162
               "ResolveBidi called on non-first continuation");
7158
               "ResolveBidi called on non-first continuation");
7163
7159
7164
  nsPresContext* presContext = PresContext();
7160
  nsPresContext* presContext = PresContext();
7165
  if (!presContext->BidiEnabled()) {
7161
  if (!presContext->BidiEnabled()) {
7166
    return NS_OK;
7162
    return NS_OK;
7167
  }
7163
  }
7168
7164
7169
  nsBidiPresUtils* bidiUtils = presContext->GetBidiUtils();
7165
  return nsBidiPresUtils::Resolve(this);
7170
  if (!bidiUtils)
7171
    return NS_ERROR_NULL_POINTER;
7172
7173
  return bidiUtils->Resolve(this);
7174
}
7166
}
7175
#endif
7167
#endif
7176
7168
7177
#ifdef DEBUG
7169
#ifdef DEBUG
7178
void
7170
void
7179
nsBlockFrame::VerifyLines(PRBool aFinalCheckOK)
7171
nsBlockFrame::VerifyLines(PRBool aFinalCheckOK)
7180
{
7172
{
7181
  if (!gVerifyLines) {
7173
  if (!gVerifyLines) {
(-)a/layout/generic/nsFrameList.cpp (-14 / +12 lines)
Line     Link Here 
 Lines 447-473   nsFrameList::GetPrevVisualFor(nsIFrame* Link Here 
447
  if (!mFirstChild)
447
  if (!mFirstChild)
448
    return nsnull;
448
    return nsnull;
449
  
449
  
450
  nsIFrame* parent = mFirstChild->GetParent();
450
  nsIFrame* parent = mFirstChild->GetParent();
451
  if (!parent)
451
  if (!parent)
452
    return aFrame ? aFrame->GetPrevSibling() : LastChild();
452
    return aFrame ? aFrame->GetPrevSibling() : LastChild();
453
453
454
  nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(mFirstChild);  
454
  nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(mFirstChild);  
455
  nsBidiPresUtils* bidiUtils = mFirstChild->PresContext()->GetBidiUtils();
456
455
457
  nsAutoLineIterator iter = parent->GetLineIterator();
456
  nsAutoLineIterator iter = parent->GetLineIterator();
458
  if (!iter) { 
457
  if (!iter) { 
459
    // Parent is not a block Frame
458
    // Parent is not a block Frame
460
    if (parent->GetType() == nsGkAtoms::lineFrame) {
459
    if (parent->GetType() == nsGkAtoms::lineFrame) {
461
      // Line frames are not bidi-splittable, so need to consider bidi reordering
460
      // Line frames are not bidi-splittable, so need to consider bidi reordering
462
      if (baseLevel == NSBIDI_LTR) {
461
      if (baseLevel == NSBIDI_LTR) {
463
        return bidiUtils->GetFrameToLeftOf(aFrame, mFirstChild, -1);
462
        return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1);
464
      } else { // RTL
463
      } else { // RTL
465
        return bidiUtils->GetFrameToRightOf(aFrame, mFirstChild, -1);
464
        return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1);
466
      }
465
      }
467
    } else {
466
    } else {
468
      // Just get the next or prev sibling, depending on block and frame direction.
467
      // Just get the next or prev sibling, depending on block and frame direction.
469
      nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild);
468
      nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild);
470
      if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) {
469
      if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) {
471
        return aFrame ? aFrame->GetPrevSibling() : LastChild();
470
        return aFrame ? aFrame->GetPrevSibling() : LastChild();
472
      } else {
471
      } else {
473
        return aFrame ? aFrame->GetNextSibling() : mFirstChild;
472
        return aFrame ? aFrame->GetNextSibling() : mFirstChild;
 Lines 492-548   nsFrameList::GetPrevVisualFor(nsIFrame* Link Here 
492
  PRInt32 numFramesOnLine;
491
  PRInt32 numFramesOnLine;
493
  nsRect lineBounds;
492
  nsRect lineBounds;
494
  PRUint32 lineFlags;
493
  PRUint32 lineFlags;
495
494
496
  if (aFrame) {
495
  if (aFrame) {
497
    iter->GetLine(thisLine, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
496
    iter->GetLine(thisLine, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
498
497
499
    if (baseLevel == NSBIDI_LTR) {
498
    if (baseLevel == NSBIDI_LTR) {
500
      frame = bidiUtils->GetFrameToLeftOf(aFrame, firstFrameOnLine, numFramesOnLine);
499
      frame = nsBidiPresUtils::GetFrameToLeftOf(aFrame, firstFrameOnLine, numFramesOnLine);
501
    } else { // RTL
500
    } else { // RTL
502
      frame = bidiUtils->GetFrameToRightOf(aFrame, firstFrameOnLine, numFramesOnLine);
501
      frame = nsBidiPresUtils::GetFrameToRightOf(aFrame, firstFrameOnLine, numFramesOnLine);
503
    }
502
    }
504
  }
503
  }
505
504
506
  if (!frame && thisLine > 0) {
505
  if (!frame && thisLine > 0) {
507
    // Get the last frame of the previous line
506
    // Get the last frame of the previous line
508
    iter->GetLine(thisLine - 1, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
507
    iter->GetLine(thisLine - 1, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
509
508
510
    if (baseLevel == NSBIDI_LTR) {
509
    if (baseLevel == NSBIDI_LTR) {
511
      frame = bidiUtils->GetFrameToLeftOf(nsnull, firstFrameOnLine, numFramesOnLine);
510
      frame = nsBidiPresUtils::GetFrameToLeftOf(nsnull, firstFrameOnLine, numFramesOnLine);
512
    } else { // RTL
511
    } else { // RTL
513
      frame = bidiUtils->GetFrameToRightOf(nsnull, firstFrameOnLine, numFramesOnLine);
512
      frame = nsBidiPresUtils::GetFrameToRightOf(nsnull, firstFrameOnLine, numFramesOnLine);
514
    }
513
    }
515
  }
514
  }
516
  return frame;
515
  return frame;
517
}
516
}
518
517
519
nsIFrame*
518
nsIFrame*
520
nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const
519
nsFrameList::GetNextVisualFor(nsIFrame* aFrame) const
521
{
520
{
522
  if (!mFirstChild)
521
  if (!mFirstChild)
523
    return nsnull;
522
    return nsnull;
524
  
523
  
525
  nsIFrame* parent = mFirstChild->GetParent();
524
  nsIFrame* parent = mFirstChild->GetParent();
526
  if (!parent)
525
  if (!parent)
527
    return aFrame ? aFrame->GetPrevSibling() : mFirstChild;
526
    return aFrame ? aFrame->GetPrevSibling() : mFirstChild;
528
527
529
  nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(mFirstChild);
528
  nsBidiLevel baseLevel = nsBidiPresUtils::GetFrameBaseLevel(mFirstChild);
530
  nsBidiPresUtils* bidiUtils = mFirstChild->PresContext()->GetBidiUtils();
531
  
529
  
532
  nsAutoLineIterator iter = parent->GetLineIterator();
530
  nsAutoLineIterator iter = parent->GetLineIterator();
533
  if (!iter) { 
531
  if (!iter) { 
534
    // Parent is not a block Frame
532
    // Parent is not a block Frame
535
    if (parent->GetType() == nsGkAtoms::lineFrame) {
533
    if (parent->GetType() == nsGkAtoms::lineFrame) {
536
      // Line frames are not bidi-splittable, so need to consider bidi reordering
534
      // Line frames are not bidi-splittable, so need to consider bidi reordering
537
      if (baseLevel == NSBIDI_LTR) {
535
      if (baseLevel == NSBIDI_LTR) {
538
        return bidiUtils->GetFrameToRightOf(aFrame, mFirstChild, -1);
536
        return nsBidiPresUtils::GetFrameToRightOf(aFrame, mFirstChild, -1);
539
      } else { // RTL
537
      } else { // RTL
540
        return bidiUtils->GetFrameToLeftOf(aFrame, mFirstChild, -1);
538
        return nsBidiPresUtils::GetFrameToLeftOf(aFrame, mFirstChild, -1);
541
      }
539
      }
542
    } else {
540
    } else {
543
      // Just get the next or prev sibling, depending on block and frame direction.
541
      // Just get the next or prev sibling, depending on block and frame direction.
544
      nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild);
542
      nsBidiLevel frameEmbeddingLevel = nsBidiPresUtils::GetFrameEmbeddingLevel(mFirstChild);
545
      if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) {
543
      if ((frameEmbeddingLevel & 1) == (baseLevel & 1)) {
546
        return aFrame ? aFrame->GetNextSibling() : mFirstChild;
544
        return aFrame ? aFrame->GetNextSibling() : mFirstChild;
547
      } else {
545
      } else {
548
        return aFrame ? aFrame->GetPrevSibling() : LastChild();
546
        return aFrame ? aFrame->GetPrevSibling() : LastChild();
 Lines 567-597   nsFrameList::GetNextVisualFor(nsIFrame* Link Here 
567
  PRInt32 numFramesOnLine;
565
  PRInt32 numFramesOnLine;
568
  nsRect lineBounds;
566
  nsRect lineBounds;
569
  PRUint32 lineFlags;
567
  PRUint32 lineFlags;
570
568
571
  if (aFrame) {
569
  if (aFrame) {
572
    iter->GetLine(thisLine, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
570
    iter->GetLine(thisLine, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
573
    
571
    
574
    if (baseLevel == NSBIDI_LTR) {
572
    if (baseLevel == NSBIDI_LTR) {
575
      frame = bidiUtils->GetFrameToRightOf(aFrame, firstFrameOnLine, numFramesOnLine);
573
      frame = nsBidiPresUtils::GetFrameToRightOf(aFrame, firstFrameOnLine, numFramesOnLine);
576
    } else { // RTL
574
    } else { // RTL
577
      frame = bidiUtils->GetFrameToLeftOf(aFrame, firstFrameOnLine, numFramesOnLine);
575
      frame = nsBidiPresUtils::GetFrameToLeftOf(aFrame, firstFrameOnLine, numFramesOnLine);
578
    }
576
    }
579
  }
577
  }
580
  
578
  
581
  PRInt32 numLines = iter->GetNumLines();
579
  PRInt32 numLines = iter->GetNumLines();
582
  if (!frame && thisLine < numLines - 1) {
580
  if (!frame && thisLine < numLines - 1) {
583
    // Get the first frame of the next line
581
    // Get the first frame of the next line
584
    iter->GetLine(thisLine + 1, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
582
    iter->GetLine(thisLine + 1, &firstFrameOnLine, &numFramesOnLine, lineBounds, &lineFlags);
585
    
583
    
586
    if (baseLevel == NSBIDI_LTR) {
584
    if (baseLevel == NSBIDI_LTR) {
587
      frame = bidiUtils->GetFrameToRightOf(nsnull, firstFrameOnLine, numFramesOnLine);
585
      frame = nsBidiPresUtils::GetFrameToRightOf(nsnull, firstFrameOnLine, numFramesOnLine);
588
    } else { // RTL
586
    } else { // RTL
589
      frame = bidiUtils->GetFrameToLeftOf(nsnull, firstFrameOnLine, numFramesOnLine);
587
      frame = nsBidiPresUtils::GetFrameToLeftOf(nsnull, firstFrameOnLine, numFramesOnLine);
590
    }
588
    }
591
  }
589
  }
592
  return frame;
590
  return frame;
593
}
591
}
594
#endif
592
#endif
595
593
596
#ifdef DEBUG_FRAME_LIST
594
#ifdef DEBUG_FRAME_LIST
597
void
595
void
(-)a/layout/generic/nsImageFrame.cpp (-15 / +11 lines)
Line     Link Here 
 Lines 1002-1032   nsImageFrame::DisplayAltText(nsPresConte Link Here 
1002
    PRUint32  maxFit;  // number of characters that fit
1002
    PRUint32  maxFit;  // number of characters that fit
1003
    nscoord strWidth = MeasureString(str, strLen, aRect.width, maxFit,
1003
    nscoord strWidth = MeasureString(str, strLen, aRect.width, maxFit,
1004
                                     aRenderingContext);
1004
                                     aRenderingContext);
1005
    
1005
    
1006
    // Display the text
1006
    // Display the text
1007
    nsresult rv = NS_ERROR_FAILURE;
1007
    nsresult rv = NS_ERROR_FAILURE;
1008
1008
1009
    if (aPresContext->BidiEnabled()) {
1009
    if (aPresContext->BidiEnabled()) {
1010
      nsBidiPresUtils* bidiUtils =  aPresContext->GetBidiUtils();
1010
      const nsStyleVisibility* vis = GetStyleVisibility();
1011
      
1011
      if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
1012
      if (bidiUtils) {
1012
        rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_RTL,
1013
        const nsStyleVisibility* vis = GetStyleVisibility();
1013
                                         aPresContext, aRenderingContext,
1014
        if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
1014
                                         aRenderingContext,
1015
          rv = bidiUtils->RenderText(str, maxFit, NSBIDI_RTL,
1015
                                         aRect.XMost() - strWidth, y + maxAscent);
1016
                                     aPresContext, aRenderingContext,
1016
      else
1017
                                     aRenderingContext,
1017
        rv = nsBidiPresUtils::RenderText(str, maxFit, NSBIDI_LTR,
1018
                                     aRect.XMost() - strWidth, y + maxAscent);
1018
                                         aPresContext, aRenderingContext,
1019
        else
1019
                                         aRenderingContext,
1020
          rv = bidiUtils->RenderText(str, maxFit, NSBIDI_LTR,
1020
                                         aRect.x, y + maxAscent);
1021
                                     aPresContext, aRenderingContext,
1022
                                     aRenderingContext,
1023
                                     aRect.x, y + maxAscent);
1024
      }
1025
    }
1021
    }
1026
    if (NS_FAILED(rv))
1022
    if (NS_FAILED(rv))
1027
      aRenderingContext.DrawString(str, maxFit, aRect.x, y + maxAscent);
1023
      aRenderingContext.DrawString(str, maxFit, aRect.x, y + maxAscent);
1028
1024
1029
    // Move to the next line
1025
    // Move to the next line
1030
    str += maxFit;
1026
    str += maxFit;
1031
    strLen -= maxFit;
1027
    strLen -= maxFit;
1032
    y += height;
1028
    y += height;
(-)a/layout/generic/nsLineBox.cpp (-3 / +1 lines)
Line     Link Here 
 Lines 658-678   nsLineIterator::CheckLineOrder(PRInt32 Link Here 
658
    *aIsReordered = PR_FALSE;
658
    *aIsReordered = PR_FALSE;
659
    *aFirstVisual = nsnull;
659
    *aFirstVisual = nsnull;
660
    *aLastVisual = nsnull;
660
    *aLastVisual = nsnull;
661
    return NS_OK;
661
    return NS_OK;
662
  }
662
  }
663
  
663
  
664
  nsPresContext* presContext = line->mFirstChild->PresContext();
664
  nsPresContext* presContext = line->mFirstChild->PresContext();
665
665
666
  nsBidiPresUtils* bidiUtils = presContext->GetBidiUtils();
667
668
  nsIFrame* leftmostFrame;
666
  nsIFrame* leftmostFrame;
669
  nsIFrame* rightmostFrame;
667
  nsIFrame* rightmostFrame;
670
  *aIsReordered = bidiUtils->CheckLineOrder(line->mFirstChild, line->GetChildCount(), &leftmostFrame, &rightmostFrame);
668
  *aIsReordered = nsBidiPresUtils::CheckLineOrder(line->mFirstChild, line->GetChildCount(), &leftmostFrame, &rightmostFrame);
671
669
672
  // map leftmost/rightmost to first/last according to paragraph direction
670
  // map leftmost/rightmost to first/last according to paragraph direction
673
  *aFirstVisual = mRightToLeft ? rightmostFrame : leftmostFrame;
671
  *aFirstVisual = mRightToLeft ? rightmostFrame : leftmostFrame;
674
  *aLastVisual = mRightToLeft ? leftmostFrame : rightmostFrame;
672
  *aLastVisual = mRightToLeft ? leftmostFrame : rightmostFrame;
675
673
676
  return NS_OK;
674
  return NS_OK;
677
}
675
}
678
#endif // IBMBIDI
676
#endif // IBMBIDI
(-)a/layout/generic/nsTextFrameThebes.cpp (-1 lines)
Line     Link Here 
 Lines 103-119    Link Here 
103
#include "nsILineIterator.h"
103
#include "nsILineIterator.h"
104
104
105
#include "nsIServiceManager.h"
105
#include "nsIServiceManager.h"
106
#ifdef ACCESSIBILITY
106
#ifdef ACCESSIBILITY
107
#include "nsAccessibilityService.h"
107
#include "nsAccessibilityService.h"
108
#endif
108
#endif
109
#include "nsAutoPtr.h"
109
#include "nsAutoPtr.h"
110
110
111
#include "nsBidiPresUtils.h"
112
#include "nsBidiUtils.h"
111
#include "nsBidiUtils.h"
113
112
114
#include "nsIThebesFontMetrics.h"
113
#include "nsIThebesFontMetrics.h"
115
#include "gfxFont.h"
114
#include "gfxFont.h"
116
#include "gfxContext.h"
115
#include "gfxContext.h"
117
#include "gfxTextRunWordCache.h"
116
#include "gfxTextRunWordCache.h"
118
#include "gfxImageSurface.h"
117
#include "gfxImageSurface.h"
119
#include "mozilla/dom/Element.h"
118
#include "mozilla/dom/Element.h"
(-)a/layout/svg/base/src/nsSVGGlyphFrame.cpp (-42 / +39 lines)
Line     Link Here 
 Lines 1525-1582   nsSVGGlyphFrame::EnsureTextRun(float *aD Link Here 
1525
  double textRunSize;
1525
  double textRunSize;
1526
  if (mTextRun) {
1526
  if (mTextRun) {
1527
    textRunSize = mTextRun->GetFontGroup()->GetStyle()->size;
1527
    textRunSize = mTextRun->GetFontGroup()->GetStyle()->size;
1528
  } else {
1528
  } else {
1529
    nsAutoString text;
1529
    nsAutoString text;
1530
    if (!GetCharacterData(text))
1530
    if (!GetCharacterData(text))
1531
      return PR_FALSE;
1531
      return PR_FALSE;
1532
1532
1533
    nsBidiPresUtils* bidiUtils = presContext->GetBidiUtils();
1533
    nsAutoString visualText;
1534
    if (bidiUtils) {
1534
      
1535
      nsAutoString visualText;
1535
    /*
1536
1536
     * XXXsmontagu: The SVG spec says:
1537
      /*
1537
     *
1538
       * XXXsmontagu: The SVG spec says:
1538
     * http://www.w3.org/TR/SVG11/text.html#DirectionProperty
1539
       *
1539
     *  "For the 'direction' property to have any effect, the 'unicode-bidi'
1540
       * http://www.w3.org/TR/SVG11/text.html#DirectionProperty
1540
     *   property's value must be embed or bidi-override."
1541
       *  "For the 'direction' property to have any effect, the 'unicode-bidi'
1541
     *
1542
       *   property's value must be embed or bidi-override."
1542
     * The SVGTiny spec, on the other hand, says 
1543
       *
1543
     *
1544
       * The SVGTiny spec, on the other hand, says 
1544
     * http://www.w3.org/TR/SVGTiny12/text.html#DirectionProperty
1545
       *
1545
     *  "For the 'direction' property to have any effect on an element that 
1546
       * http://www.w3.org/TR/SVGTiny12/text.html#DirectionProperty
1546
     *   does not by itself establish a new text chunk (such as the 'tspan'
1547
       *  "For the 'direction' property to have any effect on an element that 
1547
     *   element in SVG 1.2 Tiny), the 'unicode-bidi' property's value must
1548
       *   does not by itself establish a new text chunk (such as the 'tspan'
1548
     *   be embed or bidi-override."
1549
       *   element in SVG 1.2 Tiny), the 'unicode-bidi' property's value must
1549
     *
1550
       *   be embed or bidi-override."
1550
     * Note that this is different from HTML/CSS, where setting the 'dir'
1551
       *
1551
     *  attribute on an inline element automatically sets unicode-bidi: embed
1552
       * Note that this is different from HTML/CSS, where setting the 'dir'
1552
     *
1553
       *  attribute on an inline element automatically sets unicode-bidi: embed
1553
     * Our current implementation of bidi in SVG does not distinguish between
1554
       *
1554
     * different text elements, but treats every text container frame as a
1555
       * Our current implementation of bidi in SVG does not distinguish between
1555
     * new text chunk, so we always set the base direction according to the
1556
       * different text elements, but treats every text container frame as a
1556
     * direction property
1557
       * new text chunk, so we always set the base direction according to the
1557
     *
1558
       * direction property
1558
     * See also XXXsmontagu comments in nsSVGTextFrame::UpdateGlyphPositioning
1559
       *
1559
     */
1560
       * See also XXXsmontagu comments in nsSVGTextFrame::UpdateGlyphPositioning
1560
    
1561
       */
1561
    // Get the unicodeBidi property from the parent, because it doesn't
1562
        
1562
    // inherit
1563
      // Get the unicodeBidi property from the parent, because it doesn't
1563
    PRBool bidiOverride = (mParent->GetStyleTextReset()->mUnicodeBidi ==
1564
      // inherit
1564
                           NS_STYLE_UNICODE_BIDI_OVERRIDE);
1565
      PRBool bidiOverride = (mParent->GetStyleTextReset()->mUnicodeBidi ==
1565
    nsBidiLevel baseDirection =
1566
                             NS_STYLE_UNICODE_BIDI_OVERRIDE);
1566
      GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL ?
1567
      nsBidiLevel baseDirection =
1567
        NSBIDI_RTL : NSBIDI_LTR;
1568
        GetStyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL ?
1568
    nsBidiPresUtils::CopyLogicalToVisual(text, visualText,
1569
          NSBIDI_RTL : NSBIDI_LTR;
1569
                                         baseDirection, bidiOverride);
1570
      bidiUtils->CopyLogicalToVisual(text, visualText,
1570
    if (!visualText.IsEmpty()) {
1571
                                     baseDirection, bidiOverride);
1571
      text = visualText;
1572
      if (!visualText.IsEmpty()) {
1573
        text = visualText;
1574
      }
1575
    }
1572
    }
1576
1573
1577
    gfxMatrix m;
1574
    gfxMatrix m;
1578
    if (aForceGlobalTransform ||
1575
    if (aForceGlobalTransform ||
1579
        !(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
1576
        !(GetStateBits() & NS_STATE_SVG_NONDISPLAY_CHILD)) {
1580
      if (!GetGlobalTransform(&m))
1577
      if (!GetGlobalTransform(&m))
1581
        return PR_FALSE;
1578
        return PR_FALSE;
1582
    }
1579
    }
(-)a/layout/xul/base/src/nsTextBoxFrame.cpp (-26 / +22 lines)
Line     Link Here 
 Lines 514-555   nsTextBoxFrame::DrawText(nsIRenderingCon Link Here 
514
514
515
    aRenderingContext.SetColor(aOverrideColor ? *aOverrideColor : GetStyleColor()->mColor);
515
    aRenderingContext.SetColor(aOverrideColor ? *aOverrideColor : GetStyleColor()->mColor);
516
516
517
#ifdef IBMBIDI
517
#ifdef IBMBIDI
518
    nsresult rv = NS_ERROR_FAILURE;
518
    nsresult rv = NS_ERROR_FAILURE;
519
519
520
    if (mState & NS_FRAME_IS_BIDI) {
520
    if (mState & NS_FRAME_IS_BIDI) {
521
      presContext->SetBidiEnabled();
521
      presContext->SetBidiEnabled();
522
      nsBidiPresUtils* bidiUtils = presContext->GetBidiUtils();
522
      const nsStyleVisibility* vis = GetStyleVisibility();
523
523
      nsBidiDirection direction = (NS_STYLE_DIRECTION_RTL == vis->mDirection) ? NSBIDI_RTL : NSBIDI_LTR;
524
      if (bidiUtils) {
524
      if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
525
        const nsStyleVisibility* vis = GetStyleVisibility();
525
          // We let the RenderText function calculate the mnemonic's
526
        nsBidiDirection direction = (NS_STYLE_DIRECTION_RTL == vis->mDirection) ? NSBIDI_RTL : NSBIDI_LTR;
526
          // underline position for us.
527
        if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
527
          nsBidiPositionResolve posResolve;
528
           // We let the RenderText function calculate the mnemonic's
528
          posResolve.logicalIndex = mAccessKeyInfo->mAccesskeyIndex;
529
           // underline position for us.
529
          rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction,
530
           nsBidiPositionResolve posResolve;
530
                                           presContext, aRenderingContext,
531
           posResolve.logicalIndex = mAccessKeyInfo->mAccesskeyIndex;
531
                                           *refContext,
532
           rv = bidiUtils->RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction,
532
                                           aTextRect.x, baseline,
533
                                      presContext, aRenderingContext,
533
                                           &posResolve,
534
                                      *refContext,
534
                                           1);
535
                                      aTextRect.x, baseline,
535
          mAccessKeyInfo->mBeforeWidth = posResolve.visualLeftTwips;
536
                                      &posResolve,
536
          mAccessKeyInfo->mAccessWidth = posResolve.visualWidth;
537
                                      1);
537
      }
538
           mAccessKeyInfo->mBeforeWidth = posResolve.visualLeftTwips;
538
      else
539
           mAccessKeyInfo->mAccessWidth = posResolve.visualWidth;
539
      {
540
        }
540
          rv = nsBidiPresUtils::RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction,
541
        else
541
                                           presContext, aRenderingContext,
542
        {
542
                                           *refContext,
543
           rv = bidiUtils->RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction,
543
                                           aTextRect.x, baseline);
544
                                      presContext, aRenderingContext,
545
                                      *refContext,
546
                                      aTextRect.x, baseline);
547
        }
548
      }
544
      }
549
    }
545
    }
550
    if (NS_FAILED(rv) )
546
    if (NS_FAILED(rv) )
551
#endif // IBMBIDI
547
#endif // IBMBIDI
552
    {
548
    {
553
       aRenderingContext.SetTextRunRTL(PR_FALSE);
549
       aRenderingContext.SetTextRunRTL(PR_FALSE);
554
550
555
       if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
551
       if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
(-)a/layout/xul/base/src/tree/src/nsTreeBodyFrame.cpp (-1 / +1 lines)
Line     Link Here 
 Lines 103-119    Link Here 
103
#include "nsContentUtils.h"
103
#include "nsContentUtils.h"
104
#include "nsLayoutUtils.h"
104
#include "nsLayoutUtils.h"
105
#include "nsIScrollableFrame.h"
105
#include "nsIScrollableFrame.h"
106
#include "nsEventDispatcher.h"
106
#include "nsEventDispatcher.h"
107
#include "nsDisplayList.h"
107
#include "nsDisplayList.h"
108
#include "nsTreeBoxObject.h"
108
#include "nsTreeBoxObject.h"
109
109
110
#ifdef IBMBIDI
110
#ifdef IBMBIDI
111
#include "nsBidiPresUtils.h"
111
#include "nsBidiUtils.h"
112
#endif
112
#endif
113
113
114
// Enumeration function that cancels all the image requests in our cache
114
// Enumeration function that cancels all the image requests in our cache
115
static PLDHashOperator
115
static PLDHashOperator
116
CancelImageRequest(const nsAString& aKey,
116
CancelImageRequest(const nsAString& aKey,
117
                   nsTreeImageCacheEntry aEntry, void* aData)
117
                   nsTreeImageCacheEntry aEntry, void* aData)
118
{
118
{
119
  aEntry.request->CancelAndForgetObserver(NS_BINDING_ABORTED);
119
  aEntry.request->CancelAndForgetObserver(NS_BINDING_ABORTED);

Return to bug 624798