зеркало из https://github.com/mozilla/gecko-dev.git
Implement text-shadow for the text-overflow marker text (ellipsis) r=roc
This commit is contained in:
Родитель
53962f854b
Коммит
62ab64069b
|
@ -2889,6 +2889,61 @@ nsLayoutUtils::GetStringWidth(const nsIFrame* aFrame,
|
|||
return aContext->GetWidth(aString, aLength);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsLayoutUtils::PaintTextShadow(const nsIFrame* aFrame,
|
||||
nsRenderingContext* aContext,
|
||||
const nsRect& aTextRect,
|
||||
const nsRect& aDirtyRect,
|
||||
const nscolor& aForegroundColor,
|
||||
TextShadowCallback aCallback,
|
||||
void* aCallbackData)
|
||||
{
|
||||
const nsStyleText* textStyle = aFrame->GetStyleText();
|
||||
if (!textStyle->mTextShadow)
|
||||
return;
|
||||
|
||||
// Text shadow happens with the last value being painted at the back,
|
||||
// ie. it is painted first.
|
||||
gfxContext* aDestCtx = aContext->ThebesContext();
|
||||
for (PRUint32 i = textStyle->mTextShadow->Length(); i > 0; --i) {
|
||||
nsCSSShadowItem* shadowDetails = textStyle->mTextShadow->ShadowAt(i - 1);
|
||||
nsPoint shadowOffset(shadowDetails->mXOffset,
|
||||
shadowDetails->mYOffset);
|
||||
nscoord blurRadius = NS_MAX(shadowDetails->mRadius, 0);
|
||||
|
||||
nsRect shadowRect(aTextRect);
|
||||
shadowRect.MoveBy(shadowOffset);
|
||||
|
||||
nsPresContext* presCtx = aFrame->PresContext();
|
||||
nsContextBoxBlur contextBoxBlur;
|
||||
gfxContext* shadowContext = contextBoxBlur.Init(shadowRect, 0, blurRadius,
|
||||
presCtx->AppUnitsPerDevPixel(),
|
||||
aDestCtx, aDirtyRect, nsnull);
|
||||
if (!shadowContext)
|
||||
continue;
|
||||
|
||||
nscolor shadowColor;
|
||||
if (shadowDetails->mHasColor)
|
||||
shadowColor = shadowDetails->mColor;
|
||||
else
|
||||
shadowColor = aForegroundColor;
|
||||
|
||||
// Conjure an nsRenderingContext from a gfxContext for drawing the text
|
||||
nsRefPtr<nsRenderingContext> renderingContext = new nsRenderingContext();
|
||||
renderingContext->Init(presCtx->DeviceContext(), shadowContext);
|
||||
|
||||
aDestCtx->Save();
|
||||
aDestCtx->NewPath();
|
||||
aDestCtx->SetColor(gfxRGBA(shadowColor));
|
||||
|
||||
// The callback will draw whatever we want to blur as a shadow.
|
||||
aCallback(renderingContext, shadowOffset, shadowColor, aCallbackData);
|
||||
|
||||
contextBoxBlur.DoPaint();
|
||||
aDestCtx->Restore();
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ nscoord
|
||||
nsLayoutUtils::GetCenteredFontBaseline(nsFontMetrics* aFontMetrics,
|
||||
nscoord aLineHeight)
|
||||
|
|
|
@ -946,6 +946,23 @@ public:
|
|||
const PRUnichar* aString,
|
||||
PRInt32 aLength);
|
||||
|
||||
/**
|
||||
* Helper function for drawing text-shadow. The callback's job
|
||||
* is to draw whatever needs to be blurred onto the given context.
|
||||
*/
|
||||
typedef void (* TextShadowCallback)(nsRenderingContext* aCtx,
|
||||
nsPoint aShadowOffset,
|
||||
const nscolor& aShadowColor,
|
||||
void* aData);
|
||||
|
||||
static void PaintTextShadow(const nsIFrame* aFrame,
|
||||
nsRenderingContext* aContext,
|
||||
const nsRect& aTextRect,
|
||||
const nsRect& aDirtyRect,
|
||||
const nscolor& aForegroundColor,
|
||||
TextShadowCallback aCallback,
|
||||
void* aCallbackData);
|
||||
|
||||
/**
|
||||
* Gets the baseline to vertically center text from a font within a
|
||||
* line of specified height.
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Mats Palmgren <matspal@gmail.com> (original author)
|
||||
* Michael Ventnor <m.ventnor@gmail.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
|
@ -204,10 +205,14 @@ public:
|
|||
}
|
||||
#endif
|
||||
virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
|
||||
return mRect;
|
||||
nsRect shadowRect =
|
||||
nsLayoutUtils::GetTextShadowRectsUnion(mRect, mFrame);
|
||||
return mRect.Union(shadowRect);
|
||||
}
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx);
|
||||
void PaintTextToContext(nsRenderingContext* aCtx,
|
||||
nsPoint aOffsetFromRect);
|
||||
NS_DISPLAY_DECL_NAME("TextOverflow", TYPE_TEXT_OVERFLOW)
|
||||
private:
|
||||
nsRect mRect; // in reference frame coordinates
|
||||
|
@ -215,17 +220,43 @@ private:
|
|||
nscoord mAscent; // baseline for the marker text in mRect
|
||||
};
|
||||
|
||||
static void
|
||||
PaintTextShadowCallback(nsRenderingContext* aCtx,
|
||||
nsPoint aShadowOffset,
|
||||
const nscolor& aShadowColor,
|
||||
void* aData)
|
||||
{
|
||||
reinterpret_cast<nsDisplayTextOverflowMarker*>(aData)->
|
||||
PaintTextToContext(aCtx, aShadowOffset);
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayTextOverflowMarker::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx)
|
||||
{
|
||||
nscolor foregroundColor = nsLayoutUtils::GetTextColor(mFrame);
|
||||
|
||||
// Paint the text-shadows for the overflow marker
|
||||
nsLayoutUtils::PaintTextShadow(mFrame, aCtx, mRect, mVisibleRect,
|
||||
foregroundColor, PaintTextShadowCallback,
|
||||
(void*)this);
|
||||
|
||||
aCtx->SetColor(foregroundColor);
|
||||
PaintTextToContext(aCtx, nsPoint(0, 0));
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayTextOverflowMarker::PaintTextToContext(nsRenderingContext* aCtx,
|
||||
nsPoint aOffsetFromRect)
|
||||
{
|
||||
nsStyleContext* sc = mFrame->GetStyleContext();
|
||||
nsLayoutUtils::SetFontFromStyle(aCtx, sc);
|
||||
aCtx->SetColor(nsLayoutUtils::GetTextColor(mFrame));
|
||||
|
||||
nsPoint baselinePt = mRect.TopLeft();
|
||||
baselinePt.y += mAscent;
|
||||
nsLayoutUtils::DrawString(mFrame, aCtx, mString.get(), mString.Length(),
|
||||
baselinePt);
|
||||
|
||||
nsLayoutUtils::DrawString(mFrame, aCtx, mString.get(),
|
||||
mString.Length(), baselinePt + aOffsetFromRect);
|
||||
}
|
||||
|
||||
/* static */ TextOverflow*
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/licenses/publicdomain/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: DejaVuSansMono;
|
||||
src: url(../fonts/DejaVuSansMono.woff);
|
||||
}
|
||||
|
||||
div {
|
||||
font-family: DejaVuSansMono;
|
||||
width: 60px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
text-overflow: "...";
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
|
||||
a</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE HTML>
|
||||
<!--
|
||||
Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/licenses/publicdomain/
|
||||
|
||||
Test: Marker should have text-shadow applied to it
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
|
||||
<style type="text/css">
|
||||
@font-face {
|
||||
font-family: DejaVuSansMono;
|
||||
src: url(../fonts/DejaVuSansMono.woff);
|
||||
}
|
||||
|
||||
div {
|
||||
font-family: DejaVuSansMono;
|
||||
width: 60px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
font-size: 14px;
|
||||
text-overflow: "...";
|
||||
text-shadow: 0px 2px 2px red;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
|
||||
a</div>
|
||||
</body>
|
||||
</html>
|
|
@ -13,3 +13,4 @@ HTTP(..) == quirks-line-height.html quirks-line-height-ref.html
|
|||
HTTP(..) == standards-decorations.html standards-decorations-ref.html
|
||||
HTTP(..) == standards-line-height.html standards-line-height-ref.html
|
||||
HTTP(..) == selection.html selection-ref.html
|
||||
HTTP(..) != marker-shadow.html marker-shadow-notref.html
|
||||
|
|
|
@ -347,17 +347,46 @@ public:
|
|||
|
||||
virtual void DisableComponentAlpha() { mDisableSubpixelAA = PR_TRUE; }
|
||||
|
||||
void PaintTextWithOffset(nsRenderingContext* aCtx,
|
||||
nsPoint aOffset);
|
||||
|
||||
PRPackedBool mDisableSubpixelAA;
|
||||
};
|
||||
|
||||
static void
|
||||
PaintTextShadowCallback(nsRenderingContext* aCtx,
|
||||
nsPoint aShadowOffset,
|
||||
const nscolor& aShadowColor,
|
||||
void* aData)
|
||||
{
|
||||
reinterpret_cast<nsDisplayXULTextBox*>(aData)->
|
||||
PaintTextWithOffset(aCtx, aShadowOffset);
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayXULTextBox::Paint(nsDisplayListBuilder* aBuilder,
|
||||
nsRenderingContext* aCtx)
|
||||
{
|
||||
gfxContextAutoDisableSubpixelAntialiasing disable(aCtx->ThebesContext(),
|
||||
mDisableSubpixelAA);
|
||||
|
||||
// Paint the text shadow before doing any foreground stuff
|
||||
nsRect drawRect = static_cast<nsTextBoxFrame*>(mFrame)->mTextDrawRect;
|
||||
nsLayoutUtils::PaintTextShadow(mFrame, aCtx,
|
||||
drawRect, mVisibleRect,
|
||||
mFrame->GetStyleColor()->mColor,
|
||||
PaintTextShadowCallback,
|
||||
(void*)this);
|
||||
|
||||
PaintTextWithOffset(aCtx, nsPoint(0, 0));
|
||||
}
|
||||
|
||||
void
|
||||
nsDisplayXULTextBox::PaintTextWithOffset(nsRenderingContext* aCtx,
|
||||
nsPoint aOffset)
|
||||
{
|
||||
static_cast<nsTextBoxFrame*>(mFrame)->
|
||||
PaintTitle(*aCtx, mVisibleRect, ToReferenceFrame());
|
||||
PaintTitle(*aCtx, mVisibleRect, ToReferenceFrame() + aOffset);
|
||||
}
|
||||
|
||||
nsRect
|
||||
|
@ -395,23 +424,7 @@ nsTextBoxFrame::PaintTitle(nsRenderingContext& aRenderingContext,
|
|||
if (mTitle.IsEmpty())
|
||||
return;
|
||||
|
||||
nsRect textRect = mTextDrawRect + 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);
|
||||
DrawText(aRenderingContext, mTextDrawRect + aPt, nsnull);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -609,49 +622,6 @@ nsTextBoxFrame::DrawText(nsRenderingContext& aRenderingContext,
|
|||
}
|
||||
}
|
||||
|
||||
void nsTextBoxFrame::PaintOneShadow(gfxContext* aCtx,
|
||||
const nsRect& aTextRect,
|
||||
nsCSSShadowItem* aShadowDetails,
|
||||
const nscolor& aForegroundColor,
|
||||
const nsRect& aDirtyRect) {
|
||||
nsPoint shadowOffset(aShadowDetails->mXOffset,
|
||||
aShadowDetails->mYOffset);
|
||||
nscoord blurRadius = NS_MAX(aShadowDetails->mRadius, 0);
|
||||
|
||||
nsRect shadowRect(aTextRect);
|
||||
shadowRect.MoveBy(shadowOffset);
|
||||
|
||||
nsContextBoxBlur contextBoxBlur;
|
||||
gfxContext* shadowContext = contextBoxBlur.Init(shadowRect, 0, blurRadius,
|
||||
PresContext()->AppUnitsPerDevPixel(),
|
||||
aCtx, aDirtyRect, nsnull);
|
||||
|
||||
if (!shadowContext)
|
||||
return;
|
||||
|
||||
nscolor shadowColor;
|
||||
if (aShadowDetails->mHasColor)
|
||||
shadowColor = aShadowDetails->mColor;
|
||||
else
|
||||
shadowColor = aForegroundColor;
|
||||
|
||||
// Conjure an nsRenderingContext from a gfxContext for DrawText
|
||||
nsRefPtr<nsRenderingContext> renderingContext = new nsRenderingContext();
|
||||
renderingContext->Init(PresContext()->DeviceContext(), 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::CalculateUnderline(nsRenderingContext& aRenderingContext)
|
||||
{
|
||||
|
|
|
@ -94,6 +94,7 @@ public:
|
|||
|
||||
protected:
|
||||
friend class nsAsyncAccesskeyUpdate;
|
||||
friend class nsDisplayXULTextBox;
|
||||
// Should be called only by nsAsyncAccesskeyUpdate.
|
||||
// Returns PR_TRUE if accesskey was updated.
|
||||
PRBool UpdateAccesskey(nsWeakFrame& aWeakThis);
|
||||
|
@ -134,12 +135,6 @@ private:
|
|||
const nsRect& aTextRect,
|
||||
const nscolor* aOverrideColor);
|
||||
|
||||
void PaintOneShadow(gfxContext * aCtx,
|
||||
const nsRect& aTextRect,
|
||||
nsCSSShadowItem* aShadowDetails,
|
||||
const nscolor& aForegroundColor,
|
||||
const nsRect& aDirtyRect);
|
||||
|
||||
nsString mTitle;
|
||||
nsString mCroppedTitle;
|
||||
nsString mAccessKey;
|
||||
|
|
Загрузка…
Ссылка в новой задаче