while (data->mBreaks[breakIndex + 1] <= estimatedBreakOffset) {
while (breakIndex + 1 < data->mNumBreaks && data->mBreaks[breakIndex + 1] <= estimatedBreakOffset) {
do_BreakGetTextDimensions(const nsFontSwitchGTK *aFontSwitch,                          const PRUnichar*       aSubstring,                          PRUint32               aSubstringLength,                          void*                  aData){  nsFontGTK* fontGTK = aFontSwitch->mFontGTK;  // Make sure the font is selected  BreakGetTextDimensionsData* data = (BreakGetTextDimensionsData*)aData;  // Our current state relative to the _full_ string...  // This allows emulation of the previous code...  const PRUnichar* pstr = (const PRUnichar*)data->mOffsets->ElementAt(0);  PRInt32 numCharsFit = data->mNumCharsFit;  nscoord width = data->mWidth;  PRInt32 start = (PRInt32)(aSubstring - pstr);  PRInt32 i = start + aSubstringLength;  PRBool allDone = PR_FALSE;  while (start < i) {    // Estimate how many characters will fit. Do that by dividing the    // available space by the average character width    PRInt32 estimatedNumChars = data->mEstimatedNumChars;    if (!estimatedNumChars && data->mAveCharWidth > 0) {      estimatedNumChars = (data->mAvailWidth - width) / data->mAveCharWidth;    }    // Make sure the estimated number of characters is at least 1    if (estimatedNumChars < 1) {      estimatedNumChars = 1;    }    // Find the nearest break offset    PRInt32 estimatedBreakOffset = start + estimatedNumChars;    PRInt32 breakIndex = -1; // not yet computed    PRBool  inMiddleOfSegment = PR_FALSE;    nscoord numChars;    // Avoid scanning the break array in the case where we think all    // the text should fit    if (i <= estimatedBreakOffset) {      // Everything should fit      numChars = i - start;    }    else {      // Find the nearest place to break that is less than or equal to      // the estimated break offset      breakIndex = data->mPrevBreakState_BreakIndex;      while (data->mBreaks[breakIndex + 1] <= estimatedBreakOffset) {        ++breakIndex;      }      if (breakIndex == -1)        breakIndex = 0;      // We found a place to break that is before the estimated break      // offset. Where we break depends on whether the text crosses a      // segment boundary      if (start < data->mBreaks[breakIndex]) {        // The text crosses at least one segment boundary so measure to the        // break point just before the estimated break offset        numChars = PR_MIN(data->mBreaks[breakIndex] - start, (PRInt32)aSubstringLength);      }       else {        // See whether there is another segment boundary between this one        // and the end of the text        if ((breakIndex < (data->mNumBreaks - 1)) && (data->mBreaks[breakIndex] < i)) {          ++breakIndex;          numChars = PR_MIN(data->mBreaks[breakIndex] - start, (PRInt32)aSubstringLength);        }        else {          NS_ASSERTION(i != data->mBreaks[breakIndex], "don't expect to be at segment boundary");          // The text is all within the same segment          numChars = i - start;          // Remember we're in the middle of a segment and not between          // two segments          inMiddleOfSegment = PR_TRUE;        }      }    }    // Measure the text    nscoord twWidth, pxWidth;    if ((1 == numChars) && (pstr[start] == ' ')) {      twWidth = data->mSpaceWidth;    }    else {      pxWidth = fontGTK->GetWidth(&pstr[start], numChars);      twWidth = NSToCoordRound(float(pxWidth) * data->mP2T);    }    // See if the text fits    PRBool textFits = (twWidth + width) <= data->mAvailWidth;    // If the text fits then update the width and the number of    // characters that fit    if (textFits) {      numCharsFit += numChars;      width += twWidth;      // If we computed the break index and we're not in the middle      // of a segment then this is a spot that we can back up to if      // we need to, so remember this state      if ((breakIndex != -1) && !inMiddleOfSegment) {        data->mPrevBreakState_BreakIndex = breakIndex;        data->mPrevBreakState_Width = width;      }    }    else {      // The text didn't fit. If we're out of room then we're all done      allDone = PR_TRUE;      // See if we can just back up to the previous saved state and not      // have to measure any text      if (data->mPrevBreakState_BreakIndex != -1) {        PRBool canBackup;        // If we're in the middle of a word then the break index        // must be the same if we can use it. If we're at a segment        // boundary, then if the saved state is for the previous        // break index then we can use it        if (inMiddleOfSegment) {          canBackup = data->mPrevBreakState_BreakIndex == breakIndex;        } else {          canBackup = data->mPrevBreakState_BreakIndex == (breakIndex - 1);        }        if (canBackup) {          numCharsFit = data->mBreaks[data->mPrevBreakState_BreakIndex];          width = data->mPrevBreakState_Width;          break;        }      }      // We can't just revert to the previous break state. Find the break      // index just before the end of the text      i = start + numChars;      if (breakIndex == -1) {        breakIndex = 0;        if (data->mBreaks[breakIndex] < i) {          while ((breakIndex + 1 < data->mNumBreaks) && (data->mBreaks[breakIndex + 1] < i)) {            ++breakIndex;          }        }      }      if ((0 == breakIndex) && (i <= data->mBreaks[0])) {        // There's no place to back up to, so even though the text doesn't fit        // return it anyway        numCharsFit += numChars;        width += twWidth;        // Edge case of one word: it could be that we just measured a fragment of the        // first word and its remainder involves other fonts, so we want to keep going        // until we at least measure the entire first word        if (numCharsFit < data->mBreaks[0]) {          allDone = PR_FALSE;                   // From now on we don't care anymore what is the _real_ estimated          // number of characters that fits. Rather, we have no where to break          // and have to measure one word fully, but the real estimate is less          // than that one word. However, since the other bits of code rely on          // what is in "data->mEstimatedNumChars", we want to override          // "data->mEstimatedNumChars" and pass in what _has_ to be measured          // so that it is transparent to the other bits that depend on it.          data->mEstimatedNumChars = data->mBreaks[0] - numCharsFit;          start += numChars;        }        break;      }      // Repeatedly back up until we get to where the text fits or we're      // all the way back to the first word      width += twWidth;      while ((breakIndex >= 0) && (width > data->mAvailWidth)) {        twWidth = 0;        start = data->mBreaks[breakIndex];        numChars = i - start;        if ((1 == numChars) && (pstr[start] == ' ')) {          twWidth = data->mSpaceWidth;        }        else if (numChars > 0) {          pxWidth = fontGTK->GetWidth(&pstr[start], numChars);          twWidth = NSToCoordRound(float(pxWidth) * data->mP2T);        }        width -= twWidth;        numCharsFit = start;        --breakIndex;        i = start;      }    }    start += numChars;  }#ifdef DEBUG_rbs  NS_ASSERTION(allDone || start == i, "internal error");  NS_ASSERTION(allDone || data->mNumCharsFit != numCharsFit, "internal error");#endif /* DEBUG_rbs */  if (data->mNumCharsFit != numCharsFit) {    // some text was actually retained    data->mWidth = width;    data->mNumCharsFit = numCharsFit;    data->mFonts->AppendElement(fontGTK);    data->mOffsets->AppendElement((void*)&pstr[numCharsFit]);  }  if (allDone) {    // stop now    return PR_FALSE;  }  return PR_TRUE; // don't stop if we still need to measure more characters}