bug 721750 - support text-shadow property on ::-moz-selection. r=dbaron

This commit is contained in:
Jonathan Kew 2012-08-04 19:52:21 +01:00
parent 41cf25251b
commit 83a0c3a21a
3 changed files with 93 additions and 13 deletions

View File

@ -116,6 +116,7 @@ public:
#define NS_AUTHOR_SPECIFIED_BACKGROUND (1 << 0)
#define NS_AUTHOR_SPECIFIED_BORDER (1 << 1)
#define NS_AUTHOR_SPECIFIED_PADDING (1 << 2)
#define NS_AUTHOR_SPECIFIED_TEXT_SHADOW (1 << 3)
class nsRootPresContext;

View File

@ -304,6 +304,10 @@ public:
float* aRelativeSize,
PRUint8* aStyle);
// if this returns false, no text-shadow was specified for the selection
// and the *aShadow parameter was not modified.
bool GetSelectionShadow(nsCSSShadowArray** aShadow);
nsPresContext* PresContext() const { return mPresContext; }
enum {
@ -337,13 +341,15 @@ protected:
nsTextFrame* mFrame;
nsPresContext* mPresContext;
bool mInitCommonColors;
bool mInitSelectionColors;
bool mInitSelectionColorsAndShadow;
// Selection data
PRInt16 mSelectionStatus; // see nsIDocument.h SetDisplaySelection()
nscolor mSelectionTextColor;
nscolor mSelectionBGColor;
nsRefPtr<nsCSSShadowArray> mSelectionShadow;
bool mHasSelectionShadow;
// Common data
@ -365,7 +371,7 @@ protected:
// Color initializations
void InitCommonColors();
bool InitSelectionColors();
bool InitSelectionColorsAndShadow();
nsSelectionStyle* GetSelectionStyle(PRInt32 aIndex);
void InitSelectionStyle(PRInt32 aIndex);
@ -3390,7 +3396,8 @@ nsTextPaintStyle::nsTextPaintStyle(nsTextFrame* aFrame)
: mFrame(aFrame),
mPresContext(aFrame->PresContext()),
mInitCommonColors(false),
mInitSelectionColors(false)
mInitSelectionColorsAndShadow(false),
mHasSelectionShadow(false)
{
for (PRUint32 i = 0; i < ArrayLength(mSelectionStyle); i++)
mSelectionStyle[i].mInit = false;
@ -3434,7 +3441,7 @@ nsTextPaintStyle::GetSelectionColors(nscolor* aForeColor,
NS_ASSERTION(aForeColor, "aForeColor is null");
NS_ASSERTION(aBackColor, "aBackColor is null");
if (!InitSelectionColors())
if (!InitSelectionColorsAndShadow())
return false;
*aForeColor = mSelectionTextColor;
@ -3566,9 +3573,9 @@ FindElementAncestorForMozSelection(nsIContent* aContent)
}
bool
nsTextPaintStyle::InitSelectionColors()
nsTextPaintStyle::InitSelectionColorsAndShadow()
{
if (mInitSelectionColors)
if (mInitSelectionColorsAndShadow)
return true;
PRInt16 selectionFlags;
@ -3581,7 +3588,7 @@ nsTextPaintStyle::InitSelectionColors()
return false;
}
mInitSelectionColors = true;
mInitSelectionColorsAndShadow = true;
nsIFrame* nonGeneratedAncestor = nsLayoutUtils::GetNonGeneratedAncestor(mFrame);
Element* selectionElement =
@ -3599,6 +3606,13 @@ nsTextPaintStyle::InitSelectionColors()
mSelectionBGColor =
sc->GetVisitedDependentColor(eCSSProperty_background_color);
mSelectionTextColor = sc->GetVisitedDependentColor(eCSSProperty_color);
mHasSelectionShadow =
nsRuleNode::HasAuthorSpecifiedRules(sc,
NS_AUTHOR_SPECIFIED_TEXT_SHADOW,
true);
if (mHasSelectionShadow) {
mSelectionShadow = sc->GetStyleText()->mTextShadow;
}
return true;
}
}
@ -3759,6 +3773,21 @@ nsTextPaintStyle::GetSelectionUnderline(nsPresContext* aPresContext,
size > 0.0f;
}
bool
nsTextPaintStyle::GetSelectionShadow(nsCSSShadowArray** aShadow)
{
if (!InitSelectionColorsAndShadow()) {
return false;
}
if (mHasSelectionShadow) {
*aShadow = mSelectionShadow;
return true;
}
return false;
}
inline nscolor Get40PercentColor(nscolor aForeColor, nscolor aBackColor)
{
nscolor foreColor = NS_RGBA(NS_GET_R(aForeColor),
@ -4934,6 +4963,24 @@ static bool GetSelectionTextColors(SelectionType aType,
}
}
/**
* This sets *aShadow to the appropriate shadow, if any, for the given
* type of selection. Returns true if *aShadow was set.
* If text-shadow was not specified, *aShadow is left untouched
* (NOT reset to null), and the function returns false.
*/
static bool GetSelectionTextShadow(SelectionType aType,
nsTextPaintStyle& aTextPaintStyle,
nsCSSShadowArray** aShadow)
{
switch (aType) {
case nsISelectionController::SELECTION_NORMAL:
return aTextPaintStyle.GetSelectionShadow(aShadow);
default:
return false;
}
}
/**
* This class lets us iterate over chunks of text in a uniform selection state,
* observing cluster boundaries, in content order, maintaining the current
@ -5217,8 +5264,13 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
&foreground, &background);
gfxPoint textBaselinePt(aFramePt.x + xOffset, aTextBaselinePt.y);
// Determine what shadow, if any, to draw - either from textStyle
// or from the ::-moz-selection pseudo-class if specified there
nsCSSShadowArray *shadow = textStyle->mTextShadow;
GetSelectionTextShadow(type, aTextPaintStyle, &shadow);
// Draw shadows, if any
if (textStyle->mTextShadow) {
if (shadow) {
gfxTextRun::Metrics shadowMetrics =
mTextRun->MeasureText(offset, length, gfxFont::LOOSE_INK_EXTENTS,
nullptr, &aProvider);
@ -5226,9 +5278,9 @@ nsTextFrame::PaintTextWithSelectionColors(gfxContext* aCtx,
AddHyphenToMetrics(this, mTextRun, &shadowMetrics,
gfxFont::LOOSE_INK_EXTENTS, aCtx);
}
for (PRUint32 i = textStyle->mTextShadow->Length(); i > 0; --i) {
for (PRUint32 i = shadow->Length(); i > 0; --i) {
PaintOneShadow(offset, length,
textStyle->mTextShadow->ShadowAt(i - 1), &aProvider,
shadow->ShadowAt(i - 1), &aProvider,
dirtyRect, aFramePt, textBaselinePt, aCtx,
foreground, aClipEdges,
xOffset - (mTextRun->IsRightToLeft() ?

View File

@ -7671,8 +7671,12 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING)
inheritBits |= NS_STYLE_INHERIT_BIT(Padding);
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW)
inheritBits |= NS_STYLE_INHERIT_BIT(Text);
// properties in the SIDS, whether or not we care about them
size_t nprops = 0, backgroundOffset, borderOffset, paddingOffset;
size_t nprops = 0,
backgroundOffset, borderOffset, paddingOffset, textShadowOffset;
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
backgroundOffset = nprops;
@ -7689,6 +7693,11 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Padding);
}
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) {
textShadowOffset = nprops;
nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Text);
}
void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
AutoCSSValueArray dataArray(dataStorage, nprops);
@ -7708,6 +7717,10 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
ruleData.mValueOffsets[eStyleStruct_Padding] = paddingOffset;
}
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) {
ruleData.mValueOffsets[eStyleStruct_Text] = textShadowOffset;
}
static const nsCSSProperty backgroundValues[] = {
eCSSProperty_background_color,
eCSSProperty_background_image,
@ -7747,16 +7760,22 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
eCSSProperty_padding_end_value,
};
static const nsCSSProperty textShadowValues[] = {
eCSSProperty_text_shadow
};
// Number of properties we care about
size_t nValues = 0;
nsCSSValue* values[NS_ARRAY_LENGTH(backgroundValues) +
NS_ARRAY_LENGTH(borderValues) +
NS_ARRAY_LENGTH(paddingValues)];
NS_ARRAY_LENGTH(paddingValues) +
NS_ARRAY_LENGTH(textShadowValues)];
nsCSSProperty properties[NS_ARRAY_LENGTH(backgroundValues) +
NS_ARRAY_LENGTH(borderValues) +
NS_ARRAY_LENGTH(paddingValues)];
NS_ARRAY_LENGTH(paddingValues) +
NS_ARRAY_LENGTH(textShadowValues)];
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
for (PRUint32 i = 0, i_end = ArrayLength(backgroundValues);
@ -7782,6 +7801,14 @@ nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
}
}
if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) {
for (PRUint32 i = 0, i_end = ArrayLength(textShadowValues);
i < i_end; ++i) {
properties[nValues] = textShadowValues[i];
values[nValues++] = ruleData.ValueFor(textShadowValues[i]);
}
}
nsStyleContext* styleContext = aStyleContext;
// We need to be careful not to count styles covered up by user-important or