Attachment #493939: Patch part 3: Call ResolveParagraph on encountering <br> or embedded blocks for bug #263359

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

(-)a/layout/base/nsBidiPresUtils.cpp (-14 / +51 lines)
Line     Link Here 
 Lines 309-324   AdvanceLineIteratorToFrame(nsIFrame* aFr Link Here 
309
 *  by EnsureBidiContinuation() in previous reflows into fluid continuations.
309
 *  by EnsureBidiContinuation() in previous reflows into fluid continuations.
310
 */
310
 */
311
nsresult
311
nsresult
312
nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
312
nsBidiPresUtils::Resolve(nsBlockFrame* aBlockFrame)
313
{
313
{
314
  mLogicalFrames.Clear();
314
  mLogicalFrames.Clear();
315
  mContentToFrameIndex.Clear();
315
  mContentToFrameIndex.Clear();
316
  mBuffer.SetLength(0);
316
  mBuffer.SetLength(0);
317
  mEmbeddingStack.SetLength(0);
317
  
318
  
318
  nsPresContext *presContext = aBlockFrame->PresContext();
319
  nsPresContext *presContext = aBlockFrame->PresContext();
319
  nsIPresShell* shell = presContext->PresShell();
320
  nsIPresShell* shell = presContext->PresShell();
320
  nsStyleContext* styleContext = aBlockFrame->GetStyleContext();
321
  nsStyleContext* styleContext = aBlockFrame->GetStyleContext();
321
322
322
  // handle bidi-override being set on the block itself before calling
323
  // handle bidi-override being set on the block itself before calling
323
  // InitLogicalArray.
324
  // InitLogicalArray.
324
  const nsStyleVisibility* vis = aBlockFrame->GetStyleVisibility();
325
  const nsStyleVisibility* vis = aBlockFrame->GetStyleVisibility();
 Lines 334-375   nsBidiPresUtils::Resolve(nsBlockFrame* a Link Here 
334
    else if (NS_STYLE_DIRECTION_LTR == vis->mDirection) {
335
    else if (NS_STYLE_DIRECTION_LTR == vis->mDirection) {
335
      ch = kLRO;
336
      ch = kLRO;
336
    }
337
    }
337
    if (ch != 0) {
338
    if (ch != 0) {
338
      directionalFrame = NS_NewDirectionalFrame(shell, styleContext);
339
      directionalFrame = NS_NewDirectionalFrame(shell, styleContext);
339
      if (directionalFrame) {
340
      if (directionalFrame) {
340
        mLogicalFrames.AppendElement(directionalFrame);
341
        mLogicalFrames.AppendElement(directionalFrame);
341
        mBuffer.Append(ch);
342
        mBuffer.Append(ch);
343
        mEmbeddingStack.Append(ch);
342
      }
344
      }
343
    }
345
    }
344
  }
346
  }
345
  nsIContent* prevContent = nsnull;
347
  nsIContent* prevContent = nsnull;
346
  for (nsBlockFrame* block = aBlockFrame; block;
348
  for (nsBlockFrame* block = aBlockFrame; block;
347
       block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
349
       block = static_cast<nsBlockFrame*>(block->GetNextContinuation())) {
348
    block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
350
    block->RemoveStateBits(NS_BLOCK_NEEDS_BIDI_RESOLUTION);
349
    InitLogicalArray(block->GetFirstChild(nsnull), prevContent);
351
    InitLogicalArray(aBlockFrame, block->GetFirstChild(nsnull), prevContent);
350
  }
352
  }
351
353
352
  if (ch != 0) {
354
  if (ch != 0) {
353
    nsIFrame* directionalFrame = NS_NewDirectionalFrame(shell, styleContext);
355
    nsIFrame* directionalFrame = NS_NewDirectionalFrame(shell, styleContext);
354
    if (directionalFrame) {
356
    if (directionalFrame) {
355
      mLogicalFrames.AppendElement(directionalFrame);
357
      mLogicalFrames.AppendElement(directionalFrame);
356
      mBuffer.Append(kPDF);
358
      mBuffer.Append(kPDF);
359
      mEmbeddingStack.SetLength(mEmbeddingStack.Length() - 1);
360
    }
361
  }
362
  return ResolveParagraph(aBlockFrame, PR_FALSE);
363
}
364
365
nsresult
366
nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame, PRBool aIsMore)
367
{
368
  // XXX: TODO: Handle preformatted text ('\n')
369
  mBuffer.ReplaceChar("\t\r\n", kSpace);
370
371
  if (aIsMore) {
372
    // pop all embeddings and overrides
373
    for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) {
374
      mBuffer.Append(kPDF);
357
    }
375
    }
358
  }
376
  }
359
377
360
  // XXX: TODO: Handle preformatted text ('\n')
361
  mBuffer.ReplaceChar("\t\r\n", kSpace);
362
  return ResolveParagraph(aBlockFrame);
363
}
364
365
nsresult
366
nsBidiPresUtils::ResolveParagraph(nsBlockFrame* aBlockFrame)
367
{
368
  nsPresContext *presContext = aBlockFrame->PresContext();
378
  nsPresContext *presContext = aBlockFrame->PresContext();
369
  const nsStyleVisibility* vis = aBlockFrame->GetStyleVisibility();
379
  const nsStyleVisibility* vis = aBlockFrame->GetStyleVisibility();
370
  PRInt32 bufferLength = mBuffer.Length();
380
  PRInt32 bufferLength = mBuffer.Length();
371
381
372
  if (bufferLength < 1) {
382
  if (bufferLength < 1) {
373
    mSuccess = NS_OK;
383
    mSuccess = NS_OK;
374
    return mSuccess;
384
    return mSuccess;
375
  }
385
  }
 Lines 578-600   nsBidiPresUtils::ResolveParagraph(nsBloc Link Here 
578
        ++lineOffset;
588
        ++lineOffset;
579
      }
589
      }
580
    } // not directionalFrame
590
    } // not directionalFrame
581
    PRInt32 temp = runLength;
591
    PRInt32 temp = runLength;
582
    runLength -= fragmentLength;
592
    runLength -= fragmentLength;
583
    fragmentLength -= temp;
593
    fragmentLength -= temp;
584
594
585
    if (frame && fragmentLength <= 0) {
595
    if (frame && fragmentLength <= 0) {
586
      // If the frame is at the end of a run, split all ancestor inlines that
596
      // If the frame is at the end of a run, and this is not the end of our
587
      // need splitting.
597
      // paragrah, split all ancestor inlines that need splitting.
588
      // To determine whether we're at the end of the run, we check that we've
598
      // To determine whether we're at the end of the run, we check that we've
589
      // finished processing the current run, and that the current frame
599
      // finished processing the current run, and that the current frame
590
      // doesn't have a fluid continuation (it could have a fluid continuation
600
      // doesn't have a fluid continuation (it could have a fluid continuation
591
      // of zero length, so testing runLength alone is not sufficient).
601
      // of zero length, so testing runLength alone is not sufficient).
592
      if (runLength <= 0 && !frame->GetNextInFlow()) {
602
      if (numRun + 1 < runCount && runLength <= 0 && !frame->GetNextInFlow()) {
593
        nsIFrame* child = frame;
603
        nsIFrame* child = frame;
594
        nsIFrame* parent = frame->GetParent();
604
        nsIFrame* parent = frame->GetParent();
595
        // As long as we're on the last sibling, the parent doesn't have to be split.
605
        // As long as we're on the last sibling, the parent doesn't have to be split.
596
        // However, if the parent has a fluid continuation, we do have to make
606
        // However, if the parent has a fluid continuation, we do have to make
597
        // it non-fluid. This can happen e.g. when we have a first-letter frame
607
        // it non-fluid. This can happen e.g. when we have a first-letter frame
598
        // and the end of the first-letter coincides with the end of a
608
        // and the end of the first-letter coincides with the end of a
599
        // directional run.
609
        // directional run.
600
        while (parent &&
610
        while (parent &&
 Lines 615-642   nsBidiPresUtils::ResolveParagraph(nsBloc Link Here 
615
        // We're not at an end of a run, and |frame| is the last child of its parent.
625
        // We're not at an end of a run, and |frame| is the last child of its parent.
616
        // If its ancestors happen to have bidi continuations, convert them into
626
        // If its ancestors happen to have bidi continuations, convert them into
617
        // fluid continuations.
627
        // fluid continuations.
618
        nsIFrame* parent = frame->GetParent();
628
        nsIFrame* parent = frame->GetParent();
619
        JoinInlineAncestors(parent);
629
        JoinInlineAncestors(parent);
620
      }
630
      }
621
    }
631
    }
622
  } // for
632
  } // for
633
634
  if (aIsMore) {
635
    // Clear the frame array and paragraph buffer, and restore the stored 
636
    // embeddings and overrides
637
    mLogicalFrames.Clear();
638
    mContentToFrameIndex.Clear();
639
    mBuffer.SetLength(0);
640
    mBuffer.Append(mEmbeddingStack);
641
642
    nsIPresShell* shell = presContext->PresShell();
643
    nsStyleContext* styleContext = aBlockFrame->GetStyleContext();
644
    for (PRUint32 i = 0; i < mEmbeddingStack.Length(); ++i) {
645
      nsIFrame* dirFrame = NS_NewDirectionalFrame(shell, styleContext);
646
      if (dirFrame) {
647
        mLogicalFrames.AppendElement(dirFrame);
648
      }
649
    }
650
  }
623
  return mSuccess;
651
  return mSuccess;
624
}
652
}
625
653
626
// Should this frame be treated as a leaf (e.g. when building mLogicalFrames)?
654
// Should this frame be treated as a leaf (e.g. when building mLogicalFrames)?
627
PRBool IsBidiLeaf(nsIFrame* aFrame) {
655
PRBool IsBidiLeaf(nsIFrame* aFrame) {
628
  nsIFrame* kid = aFrame->GetFirstChild(nsnull);
656
  nsIFrame* kid = aFrame->GetFirstChild(nsnull);
629
  return !kid
657
  return !kid
630
    || !aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer);
658
    || !aFrame->IsFrameOfType(nsIFrame::eBidiInlineContainer);
631
}
659
}
632
660
633
void
661
void
634
nsBidiPresUtils::InitLogicalArray(nsIFrame*    aCurrentFrame,
662
nsBidiPresUtils::InitLogicalArray(nsBlockFrame* aBlockFrame,
663
                                  nsIFrame*    aCurrentFrame,
635
                                  nsIContent*& aPrevContent)
664
                                  nsIContent*& aPrevContent)
636
{
665
{
637
  if (!aCurrentFrame)
666
  if (!aCurrentFrame)
638
    return;
667
    return;
639
668
640
  nsIPresShell* shell = aCurrentFrame->PresContext()->PresShell();
669
  nsIPresShell* shell = aCurrentFrame->PresContext()->PresShell();
641
  nsStyleContext* styleContext;
670
  nsStyleContext* styleContext;
642
671
 Lines 686-701   nsBidiPresUtils::InitLogicalArray(nsIFra Link Here 
686
715
687
      // Create a directional frame before the first frame of an
716
      // Create a directional frame before the first frame of an
688
      // element specifying embedding or override
717
      // element specifying embedding or override
689
      if (ch != 0 && !frame->GetPrevContinuation()) {
718
      if (ch != 0 && !frame->GetPrevContinuation()) {
690
        nsIFrame* dirFrame = NS_NewDirectionalFrame(shell, styleContext);
719
        nsIFrame* dirFrame = NS_NewDirectionalFrame(shell, styleContext);
691
        if (dirFrame) {
720
        if (dirFrame) {
692
          mLogicalFrames.AppendElement(dirFrame);
721
          mLogicalFrames.AppendElement(dirFrame);
693
          mBuffer.Append(ch);
722
          mBuffer.Append(ch);
723
          mEmbeddingStack.Append(ch);
694
        }
724
        }
695
      }
725
      }
696
    }
726
    }
697
727
698
    if (IsBidiLeaf(frame)) {
728
    if (IsBidiLeaf(frame)) {
699
      /* Bidi leaf frame: add the frame to the mLogicalFrames array,
729
      /* Bidi leaf frame: add the frame to the mLogicalFrames array,
700
       * and add its index to the mContentToFrameIndex hashtable. This
730
       * and add its index to the mContentToFrameIndex hashtable. This
701
       * will be used in RemoveBidiContinuation() to identify the last
731
       * will be used in RemoveBidiContinuation() to identify the last
 Lines 712-747   nsBidiPresUtils::InitLogicalArray(nsIFra Link Here 
712
      if (nsGkAtoms::textFrame == frameType) {
742
      if (nsGkAtoms::textFrame == frameType) {
713
        if (content != aPrevContent) {
743
        if (content != aPrevContent) {
714
          aPrevContent = content;
744
          aPrevContent = content;
715
          content->AppendTextTo(mBuffer);
745
          content->AppendTextTo(mBuffer);
716
        }
746
        }
717
      } else if (nsGkAtoms::brFrame == frameType) {
747
      } else if (nsGkAtoms::brFrame == frameType) {
718
        // break frame -- append line separator
748
        // break frame -- append line separator
719
        mBuffer.Append(kLineSeparator);
749
        mBuffer.Append(kLineSeparator);
750
        ResolveParagraph(aBlockFrame, PR_TRUE);
720
      } else { 
751
      } else { 
721
        // other frame type -- see the Unicode Bidi Algorithm:
752
        // other frame type -- see the Unicode Bidi Algorithm:
722
        // "...inline objects (such as graphics) are treated as if they are ...
753
        // "...inline objects (such as graphics) are treated as if they are ...
723
        // U+FFFC"
754
        // U+FFFC"
724
        mBuffer.Append(kObjectSubstitute);
755
        mBuffer.Append(kObjectSubstitute);
756
        if (frame->GetStyleContext()->GetStyleDisplay()->mDisplay !=
757
          NS_STYLE_DISPLAY_INLINE) {
758
          // if it is not inline, end the paragraph
759
          ResolveParagraph(aBlockFrame, PR_TRUE);
760
        }
725
      }
761
      }
726
    }
762
    }
727
    else {
763
    else {
728
      nsIFrame* kid = frame->GetFirstChild(nsnull);
764
      nsIFrame* kid = frame->GetFirstChild(nsnull);
729
      InitLogicalArray(kid, aPrevContent);
765
      InitLogicalArray(aBlockFrame, kid, aPrevContent);
730
    }
766
    }
731
767
732
    // If the element is attributed by dir, indicate direction pop (add PDF frame)
768
    // If the element is attributed by dir, indicate direction pop (add PDF frame)
733
    if (ch != 0 && !frame->GetNextContinuation()) {
769
    if (ch != 0 && !frame->GetNextContinuation()) {
734
      // Create a directional frame after the last frame of an
770
      // Create a directional frame after the last frame of an
735
      // element specifying embedding or override
771
      // element specifying embedding or override
736
      nsIFrame* dirFrame = NS_NewDirectionalFrame(shell, styleContext);
772
      nsIFrame* dirFrame = NS_NewDirectionalFrame(shell, styleContext);
737
      if (dirFrame) {
773
      if (dirFrame) {
738
        mLogicalFrames.AppendElement(dirFrame);
774
        mLogicalFrames.AppendElement(dirFrame);
739
        mBuffer.Append(kPDF);
775
        mBuffer.Append(kPDF);
776
        mEmbeddingStack.SetLength(mEmbeddingStack.Length() - 1);
740
      }
777
      }
741
    }
778
    }
742
  } // for
779
  } // for
743
}
780
}
744
781
745
void
782
void
746
nsBidiPresUtils::ReorderFrames(nsIFrame*            aFirstFrameOnLine,
783
nsBidiPresUtils::ReorderFrames(nsIFrame*            aFirstFrameOnLine,
747
                               PRInt32              aNumFramesOnLine)
784
                               PRInt32              aNumFramesOnLine)
(-)a/layout/base/nsBidiPresUtils.h (-2 / +5 lines)
Line     Link Here 
 Lines 170-186   public: Link Here 
170
   * Make Bidi engine calculate the embedding levels of the frames that are
170
   * Make Bidi engine calculate the embedding levels of the frames that are
171
   * descendants of a given block frame.
171
   * descendants of a given block frame.
172
   *
172
   *
173
   * @param aBlockFrame          The block frame
173
   * @param aBlockFrame          The block frame
174
   *
174
   *
175
   *  @lina 06/18/2000
175
   *  @lina 06/18/2000
176
   */
176
   */
177
  nsresult Resolve(nsBlockFrame* aBlockFrame);
177
  nsresult Resolve(nsBlockFrame* aBlockFrame);
178
  nsresult ResolveParagraph(nsBlockFrame* aBlockFrame);
178
  nsresult ResolveParagraph(nsBlockFrame* aBlockFrame, PRBool aIsMore);
179
179
180
  /**
180
  /**
181
   * Reorder this line using Bidi engine.
181
   * Reorder this line using Bidi engine.
182
   * Update frame array, following the new visual sequence.
182
   * Update frame array, following the new visual sequence.
183
   * 
183
   * 
184
   * @lina 05/02/2000
184
   * @lina 05/02/2000
185
   */
185
   */
186
  void ReorderFrames(nsIFrame*            aFirstFrameOnLine,
186
  void ReorderFrames(nsIFrame*            aFirstFrameOnLine,
 Lines 337-353   private: Link Here 
337
                                          PRInt32                aPosResolveCount,
337
                                          PRInt32                aPosResolveCount,
338
                                          nscoord*               aWidth /* may be null */);
338
                                          nscoord*               aWidth /* may be null */);
339
339
340
  /**
340
  /**
341
   * Set up an array of the frames after splitting frames so that each frame has
341
   * Set up an array of the frames after splitting frames so that each frame has
342
   * consistent directionality. At this point the frames are still in logical
342
   * consistent directionality. At this point the frames are still in logical
343
   * order
343
   * order
344
   */
344
   */
345
  void InitLogicalArray(nsIFrame* aCurrentFrame, nsIContent*& aPrevContent);
345
  void InitLogicalArray(nsBlockFrame* aBlockFrame,
346
                        nsIFrame* aCurrentFrame,
347
                        nsIContent*& aPrevContent);
346
348
347
  /**
349
  /**
348
   * Initialize the logically-ordered array of frames
350
   * Initialize the logically-ordered array of frames
349
   * using the top-level frames of a single line
351
   * using the top-level frames of a single line
350
   */
352
   */
351
  void InitLogicalArrayFromLine(nsIFrame* aFirstFrameOnLine,
353
  void InitLogicalArrayFromLine(nsIFrame* aFirstFrameOnLine,
352
                                PRInt32   aNumFramesOnLine);
354
                                PRInt32   aNumFramesOnLine);
353
355
 Lines 467-482   private: Link Here 
467
                         PRInt32& aRunLength,
469
                         PRInt32& aRunLength,
468
                         PRInt32& aRunCount,
470
                         PRInt32& aRunCount,
469
                         PRUint8& aCharType,
471
                         PRUint8& aCharType,
470
                         PRUint8& aPrevCharType) const;
472
                         PRUint8& aPrevCharType) const;
471
  
473
  
472
  void StripBidiControlCharacters(PRUnichar* aText,
474
  void StripBidiControlCharacters(PRUnichar* aText,
473
                                  PRInt32&   aTextLength) const;
475
                                  PRInt32&   aTextLength) const;
474
  nsAutoString    mBuffer;
476
  nsAutoString    mBuffer;
477
  nsAutoString    mEmbeddingStack;
475
  nsTArray<nsIFrame*> mLogicalFrames;
478
  nsTArray<nsIFrame*> mLogicalFrames;
476
  nsTArray<nsIFrame*> mVisualFrames;
479
  nsTArray<nsIFrame*> mVisualFrames;
477
  nsDataHashtable<nsISupportsHashKey, PRInt32> mContentToFrameIndex;
480
  nsDataHashtable<nsISupportsHashKey, PRInt32> mContentToFrameIndex;
478
  PRInt32         mArraySize;
481
  PRInt32         mArraySize;
479
  PRInt32*        mIndexMap;
482
  PRInt32*        mIndexMap;
480
  PRUint8*        mLevels;
483
  PRUint8*        mLevels;
481
  nsresult        mSuccess;
484
  nsresult        mSuccess;
482
485

Return to bug 263359