PRBool bidiEnabled; aPresContext->GetBidiEnabled(&bidiEnabled); if (bidiEnabled) { nsCharType charType = eCharType_LeftToRight; PRUint32 hints = 0; aReflowState.rendContext->GetHints(hints); GetBidiProperty(aPresContext, nsLayoutAtoms::charType, (void**)&charType, sizeof(charType)); PRBool isBidiSystem = (eCharType_RightToLeftArabic == charType) ? (hints & NS_RENDERING_HINT_ARABIC_SHAPING) : (hints & NS_RENDERING_HINT_BIDI_REORDERING); aPresContext->SetIsBidiSystem(isBidiSystem);
if (ts.mSmallCaps || (0 != ts.mWordSpacing) || (0 != ts.mLetterSpacing) || ts.mJustifying) {   aPresContext->SetIsBidiSystem(PR_FALSE); } else { PRBool bidiEnabled; aPresContext->GetBidiEnabled(&bidiEnabled); if (bidiEnabled) { nsCharType charType = eCharType_LeftToRight; PRUint32 hints = 0; aReflowState.rendContext->GetHints(hints); GetBidiProperty(aPresContext, nsLayoutAtoms::charType, (void**)&charType, sizeof(charType)); PRBool isBidiSystem = (eCharType_RightToLeftArabic == charType) ? (hints & NS_RENDERING_HINT_ARABIC_SHAPING) : (hints & NS_RENDERING_HINT_BIDI_REORDERING); aPresContext->SetIsBidiSystem(isBidiSystem); }
nsTextFrame::Reflow(nsIPresContext*          aPresContext,                    nsHTMLReflowMetrics&     aMetrics,                    const nsHTMLReflowState& aReflowState,                    nsReflowStatus&          aStatus){  DO_GLOBAL_REFLOW_COUNT("nsTextFrame", aReflowState.reason);  DISPLAY_REFLOW(aPresContext, this, aReflowState, aMetrics, aStatus);#ifdef NOISY_REFLOW  ListTag(stdout);  printf(": BeginReflow: availableSize=%d,%d\n",         aReflowState.availableWidth, aReflowState.availableHeight);#endif  // XXX If there's no line layout, we shouldn't even have created this  // frame. This may happen if, for example, this is text inside a table  // but not inside a cell. For now, just don't reflow.  if (nsnull == aReflowState.mLineLayout) {    // XXX Add a method to aMetrics that does this; we do it several places    aMetrics.width = 0;    aMetrics.height = 0;    aMetrics.ascent = 0;    aMetrics.descent = 0;    if (aMetrics.mComputeMEW) {      aMetrics.mMaxElementWidth = 0;    }#ifdef MOZ_MATHML    if (NS_REFLOW_CALC_BOUNDING_METRICS & aMetrics.mFlags)      aMetrics.mBoundingMetrics.Clear();#endif    return NS_OK;  }  // Get starting offset into the content  PRInt32 startingOffset = 0;  nsIFrame* prevInFlow;  GetPrevInFlow(&prevInFlow);  if (nsnull != prevInFlow) {    nsTextFrame* prev = (nsTextFrame*)prevInFlow;    startingOffset = prev->mContentOffset + prev->mContentLength;    // If our starting offset doesn't agree with mContentOffset, then our    // prev-in-flow has changed the number of characters it maps and so we    // need to measure text and not try and optimize a resize reflow    if (startingOffset != mContentOffset) {      mState &= ~TEXT_OPTIMIZE_RESIZE;    }  }#ifdef IBMBIDI  if ( (mContentLength > 0) && (mState & NS_FRAME_IS_BIDI) ) {    startingOffset = mContentOffset;  }  PRBool bidiEnabled;  aPresContext->GetBidiEnabled(&bidiEnabled);  if (bidiEnabled) {    nsCharType charType = eCharType_LeftToRight;    PRUint32 hints = 0;    aReflowState.rendContext->GetHints(hints);    GetBidiProperty(aPresContext, nsLayoutAtoms::charType, (void**)&charType, sizeof(charType));    PRBool isBidiSystem = (eCharType_RightToLeftArabic == charType) ?                           (hints & NS_RENDERING_HINT_ARABIC_SHAPING) :                           (hints & NS_RENDERING_HINT_BIDI_REORDERING);    aPresContext->SetIsBidiSystem(isBidiSystem);  }#endif //IBMBIDI  nsLineLayout& lineLayout = *aReflowState.mLineLayout;  TextStyle ts(aPresContext, *aReflowState.rendContext, mStyleContext);  // Clear out the reflow state flags in mState (without destroying  // the TEXT_BLINK_ON bit).  PRBool lastTimeWeSkippedLeadingWS = 0 != (mState & TEXT_SKIP_LEADING_WS);  mState &= ~TEXT_REFLOW_FLAGS;  if (aReflowState.mFlags.mBlinks) {    if (0 == (mState & TEXT_BLINK_ON)) {      mState |= TEXT_BLINK_ON;      nsBlinkTimer::AddBlinkFrame(aPresContext, this);    }  }  else {    if (0 != (mState & TEXT_BLINK_ON)) {      mState &= ~TEXT_BLINK_ON;      nsBlinkTimer::RemoveBlinkFrame(this);    }  }  PRBool wrapping = (NS_STYLE_WHITESPACE_NORMAL == ts.mText->mWhiteSpace) ||    (NS_STYLE_WHITESPACE_MOZ_PRE_WRAP == ts.mText->mWhiteSpace);  // Set whitespace skip flag  PRBool skipWhitespace = PR_FALSE;  if (!ts.mPreformatted) {    if (lineLayout.GetEndsInWhiteSpace()) {      skipWhitespace = PR_TRUE;    }  }  nscoord maxWidth = aReflowState.availableWidth;  // Setup text transformer to transform this frames text content  nsCOMPtr<nsIDocument> doc;  mContent->GetDocument(*getter_AddRefs(doc));  if (!doc) {    NS_WARNING("Content has no document.");    return NS_ERROR_FAILURE;   }  nsCOMPtr<nsILineBreaker> lb;  doc->GetLineBreaker(getter_AddRefs(lb));  nsTextTransformer tx(lb, nsnull, aPresContext);  // Keep the text in ascii if possible. Note that if we're measuring small  // caps text then transform to Unicode because the helper function only  // accepts Unicode text  nsresult rv = tx.Init(this, mContent, startingOffset, !ts.mSmallCaps);  if (NS_OK != rv) {    return rv;  }  //PRInt32 contentLength = tx.GetContentLength();  // Set inWord to true if we are part of a previous piece of text's word. This  // is only valid for one pass through the measuring loop.  PRBool inWord = lineLayout.InWord() || ((nsnull != prevInFlow) && (((nsTextFrame*)prevInFlow)->mState & TEXT_FIRST_LETTER));  if (inWord) {    mState |= TEXT_IN_WORD;  }  mState &= ~TEXT_FIRST_LETTER;    PRInt32 column = lineLayout.GetColumn();  PRInt32 prevColumn = mColumn;  mColumn = column;  PRBool measureText = PR_TRUE;    // We can avoid actually measuring the text if:  // - this is a resize reflow  // - we're not dirty (see ContentChanged() function)  // - we don't have a next in flow  // - the previous reflow successfully reflowed all text in the  //   available space  // - we aren't computing the max element size (that requires we measure  //   text)  // - skipping leading whitespace is the same as it was the last time  // - we're wrapping text and the available width is at least as big as our  //   current frame width -or-  //   we're not wrapping text and we're at the same column as before (this is  //   an issue for preformatted tabbed text only)  // - AND we aren't justified (in which case the frame width has already been tweaked and can't be used)  if ((eReflowReason_Resize == aReflowState.reason) &&      (0 == (mState & NS_FRAME_IS_DIRTY))) {    nscoord realWidth = mRect.width;    if (mState & TEXT_TRIMMED_WS) {      // NOTE: Trailing whitespace includes word and letter spacing!      realWidth += ts.mSpaceWidth + ts.mWordSpacing + ts.mLetterSpacing;    }    if (!mNextInFlow &&        (mState & TEXT_OPTIMIZE_RESIZE) &&        !aMetrics.mComputeMEW &&        (lastTimeWeSkippedLeadingWS == skipWhitespace) &&        ((wrapping && (maxWidth >= realWidth)) ||         (!wrapping && (prevColumn == column))) &&#ifdef IBMBIDI        (0 == (mState & NS_FRAME_IS_BIDI) ) &&#endif // IBMBIDI        !ts.mJustifying) {      // We can skip measuring of text and use the value from our      // previous reflow      measureText = PR_FALSE;#ifdef NOISY_REFLOW      printf("  => measureText=%s wrapping=%s skipWhitespace=%s",             measureText ? "yes" : "no",             wrapping ? "yes" : "no",             skipWhitespace ? "yes" : "no");      printf(" realWidth=%d maxWidth=%d\n",             realWidth, maxWidth);#endif    }  }  // Local state passed to the routines that do the actual text measurement  TextReflowData  textData(startingOffset, wrapping, skipWhitespace,                            measureText, inWord, lineLayout.GetFirstLetterStyleOK(),                           lineLayout.LineIsBreakable(), aMetrics.mComputeMEW,                            PR_FALSE);    // Measure the text  // MeasureText may set TEXT_TRIMMED_WS flag, so don't clear after the call  if (ts.mFont->mSize)    aStatus = MeasureText(aPresContext, aReflowState, tx, lb, ts, textData);  else {    textData.mX = 0;    textData.mAscent = 0;    textData.mDescent = 0;    aStatus = NS_FRAME_COMPLETE;  }  if (textData.mTrailingSpaceTrimmed)    mState |= TEXT_TRIMMED_WS;  else    mState &= ~TEXT_TRIMMED_WS;  if (tx.HasMultibyte()) {    mState |= TEXT_HAS_MULTIBYTE;  }  // Setup metrics for caller; store final max-element-size information  aMetrics.width = textData.mX;  if ((0 == textData.mX) && !ts.mPreformatted) {    aMetrics.height = 0;    aMetrics.ascent = 0;    aMetrics.descent = 0;  }  else {    aMetrics.ascent = textData.mAscent;    aMetrics.descent = textData.mDescent;    aMetrics.height = aMetrics.ascent + aMetrics.descent;  }  mAscent = aMetrics.ascent;  if (!wrapping) {    textData.mMaxWordWidth = textData.mX;  }  if (aMetrics.mComputeMEW) {    aMetrics.mMaxElementWidth = textData.mMaxWordWidth;  }  // Set content offset and length  mContentOffset = startingOffset;  mContentLength = textData.mOffset - startingOffset;  // Compute space and letter counts for justification, if required  if (ts.mJustifying) {    PRInt32 numSpaces;    PRInt32 textLength;    // This will include a space for trailing whitespace, if any is present.    // This is corrected for in nsLineLayout::TrimWhiteSpaceIn.    // This work could be done in MeasureText, but it's complex to do accurately    // there because of the need to repair counts when wrapped words are backed out.    // So I do it via PrepareUnicodeText ... a little slower perhaps, but a lot saner,    // and it localizes the counting logic to one place.    numSpaces = PrepareUnicodeText(tx, nsnull, nsnull, &textLength);    lineLayout.SetTextJustificationWeights(numSpaces, textLength - numSpaces);  }#ifdef MOZ_MATHML  // Simple minded code to also return the bounding metrics if the caller wants it...  // More consolidation is needed -- a better approach is to follow what is done by  // the other routines that are doing measurements.  if (NS_REFLOW_CALC_BOUNDING_METRICS & aMetrics.mFlags) {    rv = NS_ERROR_UNEXPECTED; // initialize with an error; it is reset if things turn out well    aMetrics.mBoundingMetrics.Clear();    // Get the text to measure.     nsCOMPtr<nsIDOMText> domText(do_QueryInterface(mContent));    if (domText.get()) {      nsAutoString aData;      domText->GetData(aData);      // Extract the piece of text relevant to us -- XXX whitespace cause a mess here        nsAutoString aText;      aData.Mid(aText, mContentOffset, mContentLength);      // Set the font      SetFontFromStyle(aReflowState.rendContext, mStyleContext);      // Now get the exact bounding metrics of the text      nsBoundingMetrics bm;      rv = aReflowState.rendContext->GetBoundingMetrics(aText.get(), PRUint32(mContentLength), bm);      if (NS_SUCCEEDED(rv)) aMetrics.mBoundingMetrics = bm;    }    if (NS_FAILED(rv)) {       // Things didn't turn out well, just return the reflow metrics.      aMetrics.mBoundingMetrics.ascent  = aMetrics.ascent;      aMetrics.mBoundingMetrics.descent = aMetrics.descent;      aMetrics.mBoundingMetrics.width   = aMetrics.width;#ifdef MOZ_MATHML_BOUNDINGMETRICS      printf("nsTextFrame: could not perform GetBoundingMetrics()\n");#endif    }  }#endif  nscoord maxFrameWidth  = mRect.width;  nscoord maxFrameHeight = mRect.height;  // For future resize reflows we would like to avoid measuring the text.  // We can only do this if after this reflow we're:  // - complete. If we're not complete then our desired width doesn't  //   represent our total size  // - we fit in the available space. We may be complete, but if we  //   return a larger desired width than is available we may get pushed  //   and our frame width won't get set  if (NS_FRAME_IS_COMPLETE(aStatus) && !NS_INLINE_IS_BREAK(aStatus)  &&       (aMetrics.width <= maxWidth)) {    mState |= TEXT_OPTIMIZE_RESIZE;    mRect.width = aMetrics.width;  }  else {    mState &= ~TEXT_OPTIMIZE_RESIZE;  }   // If it's an incremental reflow command, then invalidate our existing  // bounds.  // XXX We need a finer granularity than this, but it isn't clear what  // has actually changed...  /*if (eReflowReason_Incremental == aReflowState.reason ||      eReflowReason_Dirty == aReflowState.reason) {*/    // XXX See bug 71523 We should really adjust the frames x coordinate to    // a pixel boundary to solve this.     // For now we add 1 pixel to the width of the invalidated rect.    // This fixes cases where the twips to pixel roundoff causes the invalidated    // rect's width to be one pixel short.     float p2t;    aPresContext->GetScaledPixelsToTwips(&p2t);    nscoord onePixel = NSIntPixelsToTwips(1, p2t);    maxFrameWidth  = PR_MAX(maxFrameWidth,  mRect.width) + onePixel;     maxFrameHeight = PR_MAX(maxFrameHeight, mRect.height);    nsRect damage(0,0,maxFrameWidth,maxFrameHeight);    if (!damage.IsEmpty()) {      Invalidate(aPresContext, damage);    }  /*}*/#ifdef NOISY_REFLOW  ListTag(stdout);  printf(": desiredSize=%d,%d(a=%d/d=%d) status=%x\n",         aMetrics.width, aMetrics.height, aMetrics.ascent, aMetrics.descent,         aStatus);#endif  NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);  return NS_OK;}