Bug 438517 - Add text-shadow support to nsTextBoxFrame r+sr=roc

This commit is contained in:
Rob Arnold 2008-09-30 20:57:51 -04:00
parent 09cfc5fa8c
commit d1621dec9e
2 changed files with 129 additions and 37 deletions

View File

@ -369,35 +369,30 @@ nsTextBoxFrame::PaintTitle(nsIRenderingContext& aRenderingContext,
if (mTitle.IsEmpty())
return;
nsRect textRect(aPt, GetSize());
textRect.Deflate(GetUsedBorderAndPadding());
nsRect textRect(CalcTextRect(aRenderingContext, aPt));
// determine (cropped) title and underline position
nsPresContext* presContext = PresContext();
LayoutTitle(presContext, aRenderingContext, textRect);
// make the rect as small as our (cropped) text.
nscoord outerWidth = textRect.width;
textRect.width = mTitleWidth;
// Align our text within the overall rect by checking our text-align property.
const nsStyleVisibility* vis = GetStyleVisibility();
// Paint the text shadow before doing any foreground stuff
const nsStyleText* textStyle = GetStyleText();
if (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_CENTER)
textRect.x += (outerWidth - textRect.width)/2;
else if (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_RIGHT) {
if (vis->mDirection == NS_STYLE_DIRECTION_LTR)
textRect.x += (outerWidth - textRect.width);
}
else {
if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
textRect.x += (outerWidth - textRect.width);
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);
}
}
// don't draw if the title is not dirty
if (PR_FALSE == aDirtyRect.Intersects(textRect))
return;
DrawText(aRenderingContext, textRect, 0);
}
void
nsTextBoxFrame::DrawText(nsIRenderingContext& aRenderingContext,
const nsRect& aTextRect,
const nscolor& aOverrideColor)
{
nsPresContext* presContext = PresContext();
// paint the title
nscolor overColor;
@ -414,7 +409,7 @@ nsTextBoxFrame::PaintTitle(nsIRenderingContext& aRenderingContext,
const nsStyleTextReset* styleText = context->GetStyleTextReset();
if (decorMask & styleText->mTextDecoration) { // a decoration defined here
nscolor color = context->GetStyleColor()->mColor;
nscolor color = aOverrideColor ? aOverrideColor : context->GetStyleColor()->mColor;
if (NS_STYLE_TEXT_DECORATION_UNDERLINE & decorMask & styleText->mTextDecoration) {
underColor = color;
@ -449,11 +444,11 @@ nsTextBoxFrame::PaintTitle(nsIRenderingContext& aRenderingContext,
fontMet->GetMaxAscent(ascent);
nscoord baseline =
presContext->RoundAppUnitsToNearestDevPixels(textRect.y + ascent);
presContext->RoundAppUnitsToNearestDevPixels(aTextRect.y + ascent);
nsRefPtr<gfxContext> ctx = aRenderingContext.ThebesContext();
gfxPoint pt(presContext->AppUnitsToGfxUnits(textRect.x),
presContext->AppUnitsToGfxUnits(textRect.y));
gfxFloat width = presContext->AppUnitsToGfxUnits(textRect.width);
gfxPoint pt(presContext->AppUnitsToGfxUnits(aTextRect.x),
presContext->AppUnitsToGfxUnits(aTextRect.y));
gfxFloat width = presContext->AppUnitsToGfxUnits(aTextRect.width);
gfxFloat ascentPixel = presContext->AppUnitsToGfxUnits(ascent);
if (decorations & (NS_FONT_DECORATION_OVERLINE | NS_FONT_DECORATION_UNDERLINE)) {
fontMet->GetUnderline(offset, size);
@ -489,7 +484,7 @@ nsTextBoxFrame::PaintTitle(nsIRenderingContext& aRenderingContext,
CalculateUnderline(aRenderingContext);
aRenderingContext.SetColor(GetStyleColor()->mColor);
aRenderingContext.SetColor(aOverrideColor ? aOverrideColor : GetStyleColor()->mColor);
#ifdef IBMBIDI
nsresult rv = NS_ERROR_FAILURE;
@ -508,7 +503,7 @@ nsTextBoxFrame::PaintTitle(nsIRenderingContext& aRenderingContext,
posResolve.logicalIndex = mAccessKeyInfo->mAccesskeyIndex;
rv = bidiUtils->RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction,
presContext, aRenderingContext,
textRect.x, baseline,
aTextRect.x, baseline,
&posResolve,
1);
mAccessKeyInfo->mBeforeWidth = posResolve.visualLeftTwips;
@ -517,7 +512,7 @@ nsTextBoxFrame::PaintTitle(nsIRenderingContext& aRenderingContext,
{
rv = bidiUtils->RenderText(mCroppedTitle.get(), mCroppedTitle.Length(), direction,
presContext, aRenderingContext,
textRect.x, baseline);
aTextRect.x, baseline);
}
}
}
@ -537,17 +532,63 @@ nsTextBoxFrame::PaintTitle(nsIRenderingContext& aRenderingContext,
mAccessKeyInfo->mBeforeWidth = 0;
}
aRenderingContext.DrawString(mCroppedTitle, textRect.x, baseline);
aRenderingContext.DrawString(mCroppedTitle, aTextRect.x, baseline);
}
if (mAccessKeyInfo && mAccessKeyInfo->mAccesskeyIndex != kNotFound) {
aRenderingContext.FillRect(textRect.x + mAccessKeyInfo->mBeforeWidth,
textRect.y + mAccessKeyInfo->mAccessOffset,
aRenderingContext.FillRect(aTextRect.x + mAccessKeyInfo->mBeforeWidth,
aTextRect.y + mAccessKeyInfo->mAccessOffset,
mAccessKeyInfo->mAccessWidth,
mAccessKeyInfo->mAccessUnderlineSize);
}
}
void nsTextBoxFrame::PaintOneShadow(gfxContext* aCtx,
const nsRect& aTextRect,
nsCSSShadowItem* aShadowDetails,
const nscolor& aForegroundColor) {
nsPoint shadowOffset(aShadowDetails->mXOffset,
aShadowDetails->mYOffset);
nscoord blurRadius = PR_MAX(aShadowDetails->mRadius, 0);
nsRect shadowRect(aTextRect);
shadowRect.MoveBy(shadowOffset);
gfxRect shadowRectGFX(shadowRect.x, shadowRect.y, shadowRect.width, shadowRect.height);
nsContextBoxBlur contextBoxBlur;
gfxContext* shadowContext = contextBoxBlur.Init(shadowRectGFX, blurRadius,
PresContext()->AppUnitsPerDevPixel(),
aCtx);
if (!shadowContext)
return;
nscolor shadowColor;
if (aShadowDetails->mHasColor)
shadowColor = aShadowDetails->mColor;
else
shadowColor = aForegroundColor;
// Conjure an nsIRenderingContext from a gfxContext for DrawText
nsCOMPtr<nsIRenderingContext> renderingContext = nsnull;
nsIDeviceContext* devCtx = PresContext()->DeviceContext();
devCtx->CreateRenderingContextInstance(*getter_AddRefs(renderingContext));
if (!renderingContext) return;
renderingContext->Init(devCtx, shadowContext);
aCtx->Save();
aCtx->NewPath();
aCtx->SetColor(gfxRGBA(shadowColor));
// Draw the text onto our alpha-only surface to capture the alpha values.
// Remember that the box blur context has a device offset on it, so we don't need to
// translate any coordinates to fit on the surface.
DrawText(*renderingContext, shadowRect, shadowColor);
contextBoxBlur.DoPaint();
aCtx->Restore();
}
void
nsTextBoxFrame::LayoutTitle(nsPresContext* aPresContext,
nsIRenderingContext& aRenderingContext,
@ -888,7 +929,16 @@ nsTextBoxFrame::DoLayout(nsBoxLayoutState& aBoxLayoutState)
mState |= NS_STATE_NEED_LAYOUT;
return nsLeafBoxFrame::DoLayout(aBoxLayoutState);
nsresult rv = nsLeafBoxFrame::DoLayout(aBoxLayoutState);
const nsStyleText* textStyle = GetStyleText();
if (textStyle->mTextShadow) {
nsPoint origin(0,0);
nsRect textRect = CalcTextRect(*aBoxLayoutState.GetRenderingContext(), origin);
nsRect overflowRect(nsLayoutUtils::GetTextShadowRectsUnion(textRect, this));
FinishAndStoreOverflow(&overflowRect, GetSize());
}
return rv;
}
/* virtual */ void
@ -928,6 +978,36 @@ nsTextBoxFrame::CalcTextSize(nsBoxLayoutState& aBoxLayoutState)
}
}
nsRect
nsTextBoxFrame::CalcTextRect(nsIRenderingContext &aRenderingContext, const nsPoint &aTextOrigin)
{
nsRect textRect(aTextOrigin, GetSize());
textRect.Deflate(GetUsedBorderAndPadding());
// determine (cropped) title and underline position
nsPresContext* presContext = PresContext();
LayoutTitle(presContext, aRenderingContext, textRect);
// make the rect as small as our (cropped) text.
nscoord outerWidth = textRect.width;
textRect.width = mTitleWidth;
// Align our text within the overall rect by checking our text-align property.
const nsStyleVisibility* vis = GetStyleVisibility();
const nsStyleText* textStyle = GetStyleText();
if (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_CENTER)
textRect.x += (outerWidth - textRect.width)/2;
else if (textStyle->mTextAlign == NS_STYLE_TEXT_ALIGN_RIGHT) {
if (vis->mDirection == NS_STYLE_DIRECTION_LTR)
textRect.x += (outerWidth - textRect.width);
}
else {
if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
textRect.x += (outerWidth - textRect.width);
}
return textRect;
}
/**
* Ok return our dimensions
*/

View File

@ -104,6 +104,8 @@ protected:
void CalcTextSize(nsBoxLayoutState& aBoxLayoutState);
nsRect CalcTextRect(nsIRenderingContext &aRenderingContext, const nsPoint &aTextOrigin);
nsTextBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext);
void CalculateTitleForWidth(nsPresContext* aPresContext,
@ -123,6 +125,16 @@ private:
PRBool AlwaysAppendAccessKey();
PRBool InsertSeparatorBeforeAccessKey();
void DrawText(nsIRenderingContext& aRenderingContext,
const nsRect& aTextRect,
const nscolor& aOverrideColor);
void PaintOneShadow(gfxContext * aCtx,
const nsRect& aTextRect,
nsCSSShadowItem* aShadowDetails,
const nscolor& aForegroundColor);
CroppingStyle mCropType;
nsString mTitle;
nsString mCroppedTitle;