зеркало из https://github.com/mozilla/pjs.git
Bug 438517 - Add text-shadow support to nsTextBoxFrame r+sr=roc
This commit is contained in:
Родитель
9dbcb66b3f
Коммит
a9721a71dc
|
@ -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);
|
||||
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);
|
||||
}
|
||||
else {
|
||||
if (vis->mDirection == NS_STYLE_DIRECTION_RTL)
|
||||
textRect.x += (outerWidth - textRect.width);
|
||||
}
|
||||
|
||||
// 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
|
||||
*/
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче