void nsTextBoxFrame::PaintTitle(nsIRenderingContext& aRenderingContext, const nsRect& aDirtyRect, nsPoint aPt) { if (mTitle.IsEmpty()) return; nsRect textRect(CalcTextRect(aRenderingContext, aPt)); // Paint the text shadow before doing any foreground stuff const nsStyleText* textStyle = GetStyleText(); if (textStyle->mTextShadow) { // Text shadow happens with the last value being painted at the back, // ie. it is painted first. for (PRUint32 i = textStyle->mTextShadow->Length(); i > 0; --i) { PaintOneShadow(aRenderingContext.ThebesContext(), textRect, textStyle->mTextShadow->ShadowAt(i - 1), GetStyleColor()->mColor, aDirtyRect); } } DrawText(aRenderingContext, textRect, nsnull); }
void nsTextBoxFrame::DrawText(nsIRenderingContext& aRenderingContext, const nsRect& aTextRect, const nscolor* aOverrideColor) { nsPresContext* presContext = PresContext(); // paint the title nscolor overColor; nscolor underColor; nscolor strikeColor; nsStyleContext* context = mStyleContext; PRUint8 decorations = NS_STYLE_TEXT_DECORATION_NONE; // Begin with no decorations PRUint8 decorMask = NS_STYLE_TEXT_DECORATION_UNDERLINE | NS_STYLE_TEXT_DECORATION_OVERLINE | NS_STYLE_TEXT_DECORATION_LINE_THROUGH; // A mask of all possible decorations. PRBool hasDecorations = context->HasTextDecorations(); do { // find decoration colors const nsStyleTextReset* styleText = context->GetStyleTextReset(); if (decorMask & styleText->mTextDecoration) { // a decoration defined here nscolor color = aOverrideColor ? *aOverrideColor : context->GetStyleColor()->mColor; if (NS_STYLE_TEXT_DECORATION_UNDERLINE & decorMask & styleText->mTextDecoration) { underColor = color; decorMask &= ~NS_STYLE_TEXT_DECORATION_UNDERLINE; decorations |= NS_STYLE_TEXT_DECORATION_UNDERLINE; } if (NS_STYLE_TEXT_DECORATION_OVERLINE & decorMask & styleText->mTextDecoration) { overColor = color; decorMask &= ~NS_STYLE_TEXT_DECORATION_OVERLINE; decorations |= NS_STYLE_TEXT_DECORATION_OVERLINE; } if (NS_STYLE_TEXT_DECORATION_LINE_THROUGH & decorMask & styleText->mTextDecoration) { strikeColor = color; decorMask &= ~NS_STYLE_TEXT_DECORATION_LINE_THROUGH; decorations |= NS_STYLE_TEXT_DECORATION_LINE_THROUGH; } } if (0 != decorMask) { context = context->GetParent(); if (context) { hasDecorations = context->HasTextDecorations(); } } } while (context && hasDecorations && (0 != decorMask)); nsCOMPtr<nsIFontMetrics> fontMet; nsLayoutUtils::GetFontMetricsForFrame(this, getter_AddRefs(fontMet)); nscoord offset; nscoord size; nscoord ascent; fontMet->GetMaxAscent(ascent); nscoord baseline = presContext->RoundAppUnitsToNearestDevPixels(aTextRect.y + ascent); nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext(); gfxPoint pt(presContext->AppUnitsToGfxUnits(aTextRect.x), presContext->AppUnitsToGfxUnits(aTextRect.y)); gfxFloat width = presContext->AppUnitsToGfxUnits(aTextRect.width); gfxFloat ascentPixel = presContext->AppUnitsToGfxUnits(ascent); // Underlines are drawn before overlines, and both before the text // itself, per http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1. // (We don't apply this rule to the access-key underline because we only // find out where that is as a side effect of drawing the text, in the // general case -- see below.) if (decorations & (NS_FONT_DECORATION_OVERLINE | NS_FONT_DECORATION_UNDERLINE)) { fontMet->GetUnderline(offset, size); gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset); gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size); if (decorations & NS_FONT_DECORATION_UNDERLINE) { nsCSSRendering::PaintDecorationLine(ctx, underColor, pt, gfxSize(width, sizePixel), ascentPixel, offsetPixel, NS_STYLE_TEXT_DECORATION_UNDERLINE, nsCSSRendering::DECORATION_STYLE_SOLID); } if (decorations & NS_FONT_DECORATION_OVERLINE) { nsCSSRendering::PaintDecorationLine(ctx, overColor, pt, gfxSize(width, sizePixel), ascentPixel, ascentPixel, NS_STYLE_TEXT_DECORATION_OVERLINE, nsCSSRendering::DECORATION_STYLE_SOLID); } } aRenderingContext.SetFont(fontMet); CalculateUnderline(aRenderingContext); aRenderingContext.SetColor(aOverrideColor ? *aOverrideColor : GetStyleColor()->mColor); #ifdef IBMBIDI nsresult rv = NS_ERROR_FAILURE; if (mState & NS_FRAME_IS_BIDI) { presContext->SetBidiEnabled(); nsBidiPresUtils* bidiUtils = presContext->GetBidiUtils(); if (bidiUtils) { const nsStyleVisibility* vis = GetStyleVisibility(); nsBidiDirection direction = (NS_STYLE_DIRECTION_RTL == vis->mDirection) ? NSBIDI_RTL : NSBIDI_LTR; if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { // We let the RenderText function calculate the mnemonic's // underline position for us. nsBidiPositionResolve posResolve; posResolve.logicalIndex = mAccessKeyInfo->mAccesskeyIndex; rv = bidiUtils->RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction, presContext, aRenderingContext, aTextRect.x, baseline, &posResolve, 1); mAccessKeyInfo->mBeforeWidth = posResolve.visualLeftTwips; mAccessKeyInfo->mAccessWidth = posResolve.visualWidth; } else { rv = bidiUtils->RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction, presContext, aRenderingContext, aTextRect.x, baseline); } } } if (NS_FAILED(rv) ) #endif // IBMBIDI { aRenderingContext.SetTextRunRTL(PR_FALSE); if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { // In the simple (non-BiDi) case, we calculate the mnemonic's // underline position by getting the text metric. // XXX are attribute values always two byte? if (mAccessKeyInfo->mAccesskeyIndex > 0) aRenderingContext.GetWidth(mCroppedTitle.get(), mAccessKeyInfo->mAccesskeyIndex, mAccessKeyInfo->mBeforeWidth); else mAccessKeyInfo->mBeforeWidth = 0; } aRenderingContext.DrawString(mCroppedTitle, aTextRect.x, baseline); } if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) { aRenderingContext.FillRect(aTextRect.x + mAccessKeyInfo->mBeforeWidth, aTextRect.y + mAccessKeyInfo->mAccessOffset, mAccessKeyInfo->mAccessWidth, mAccessKeyInfo->mAccessUnderlineSize); } // Strikeout is drawn on top of the text, per // http://www.w3.org/TR/CSS21/zindex.html point 7.2.1.4.1.1. if (decorations & NS_FONT_DECORATION_LINE_THROUGH) { fontMet->GetStrikeout(offset, size); gfxFloat offsetPixel = presContext->AppUnitsToGfxUnits(offset); gfxFloat sizePixel = presContext->AppUnitsToGfxUnits(size); nsCSSRendering::PaintDecorationLine(ctx, strikeColor, pt, gfxSize(width, sizePixel), ascentPixel, offsetPixel, NS_STYLE_TEXT_DECORATION_LINE_THROUGH, nsCSSRendering::DECORATION_STYLE_SOLID); } }