ch = XP_TO_UPPER(ch);
ch = nsCRT::ToUpper(ch);
TextFrame::RenderString(nsIRenderingContext& aRenderingContext,                        nsIStyleContext* aStyleContext,                        TextStyle& aTextStyle,                        PRUnichar* aBuffer, PRInt32 aLength,                        nscoord aX, nscoord aY,                        nscoord aWidth){  PRUnichar buf[TEXT_BUF_SIZE];  PRUnichar* bp0 = buf;  if (aLength > TEXT_BUF_SIZE) {    bp0 = new PRUnichar[aLength];  }  PRUnichar* bp = bp0;  PRBool spacing = (0 != aTextStyle.mLetterSpacing) ||    (0 != aTextStyle.mWordSpacing) || (mRect.width > mComputedWidth);  nscoord spacingMem[TEXT_BUF_SIZE];  PRIntn* sp0 = spacingMem;   if (spacing && (aLength > TEXT_BUF_SIZE)) {    sp0 = new nscoord[aLength];  }  PRIntn* sp = sp0;  nscoord smallY = aY;  if (aTextStyle.mSmallCaps) {    nscoord normalAscent, smallAscent;    aTextStyle.mNormalFont->GetMaxAscent(normalAscent);    aTextStyle.mSmallFont->GetMaxAscent(smallAscent);    if (normalAscent > smallAscent) {      smallY = aY + normalAscent - smallAscent;    }  }  nsIFontMetrics* lastFont = aTextStyle.mLastFont;  nscoord lastY = aY;  if (lastFont == aTextStyle.mSmallFont) {    lastY = smallY;  }  PRInt32 pendingCount;  PRUnichar* runStart = bp;  nscoord charWidth, width = 0;  for (; --aLength >= 0; aBuffer++) {    nsIFontMetrics* nextFont;    nscoord nextY, glyphWidth;    PRUnichar ch = *aBuffer;    if (aTextStyle.mSmallCaps && XP_IS_LOWERCASE(ch)) {      nextFont = aTextStyle.mSmallFont;      nextY = smallY;      ch = XP_TO_UPPER(ch);      if (lastFont != aTextStyle.mSmallFont) {        aRenderingContext.SetFont(aTextStyle.mSmallFont);        aRenderingContext.GetWidth(ch, charWidth);        aRenderingContext.SetFont(aTextStyle.mNormalFont);      }      else {        aRenderingContext.GetWidth(ch, charWidth);      }      glyphWidth = charWidth + aTextStyle.mLetterSpacing;    }    else if (ch == ' ') {      nextFont = aTextStyle.mNormalFont;      nextY = aY;      glyphWidth = aTextStyle.mSpaceWidth + aTextStyle.mWordSpacing;      nscoord extra = aTextStyle.mExtraSpacePerSpace;      if (--aTextStyle.mNumSpaces == 0) {        extra += aTextStyle.mRemainingExtraSpace;      }      glyphWidth += extra;    }    else {      if (lastFont != aTextStyle.mNormalFont) {        aRenderingContext.SetFont(aTextStyle.mNormalFont);        aRenderingContext.GetWidth(ch, charWidth);        aRenderingContext.SetFont(aTextStyle.mSmallFont);      }      else {        aRenderingContext.GetWidth(ch, charWidth);      }      nextFont = aTextStyle.mNormalFont;      nextY = aY;      glyphWidth = charWidth + aTextStyle.mLetterSpacing;    }    if (nextFont != lastFont) {      pendingCount = bp - runStart;      if (0 != pendingCount) {        // Measure previous run of characters using the previous font        aRenderingContext.DrawString(runStart, pendingCount,                                     aX, lastY, -1,                                     spacing ? sp0 : nsnull);        // Note: use aY not small-y so that decorations are drawn with        // respect to the normal-font not the current font.        PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle,                             aX, aY, width);        aWidth -= width;        aX += width;        runStart = bp = bp0;        sp = sp0;        width = 0;      }      aRenderingContext.SetFont(nextFont);      lastFont = nextFont;      lastY = nextY;    }    *bp++ = ch;    *sp++ = glyphWidth;    width += glyphWidth;  }  pendingCount = bp - runStart;  if (0 != pendingCount) {    // Measure previous run of characters using the previous font    aRenderingContext.DrawString(runStart, pendingCount, aX, lastY, -1,                                 spacing ? sp0 : nsnull);    // Note: use aY not small-y so that decorations are drawn with    // respect to the normal-font not the current font.    PaintTextDecorations(aRenderingContext, aStyleContext, aTextStyle,                         aX, aY, aWidth);  }  aTextStyle.mLastFont = lastFont;  if (bp0 != buf) {    delete [] bp0;  }  if (sp0 != spacingMem) {    delete [] sp0;  }}