Bug 686281 - Implement CSS mask style; r=dbaron.

This commit is contained in:
CJKu 2016-01-28 06:28:00 +01:00
parent 538b854ad1
commit 577578571f
10 changed files with 398 additions and 102 deletions

View File

@ -732,6 +732,56 @@ nsFrame::GetOffsets(int32_t &aStart, int32_t &aEnd) const
return NS_OK;
}
static
void
AddAndRemoveImageAssociations(nsFrame* aFrame,
const nsStyleImageLayers* aOldLayers,
const nsStyleImageLayers* aNewLayers)
{
ImageLoader* imageLoader =
aFrame->PresContext()->Document()->StyleImageLoader();
// If the old context had a background-image image, or mask-image image,
// and new context does not have the same image, clear the image load
// notifier (which keeps the image loading, if it still is) for the frame.
// We want to do this conservatively because some frames paint their
// backgrounds from some other frame's style data, and we don't want
// to clear those notifiers unless we have to. (They'll be reset
// when we paint, although we could miss a notification in that
// interval.)
if (aOldLayers) {
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, (*aOldLayers)) {
// If there is an image in oldBG that's not in newBG, drop it.
if (i >= aNewLayers->mImageCount ||
!aOldLayers->mLayers[i].mImage.ImageDataEquals(
aNewLayers->mLayers[i].mImage)) {
const nsStyleImage& oldImage = aOldLayers->mLayers[i].mImage;
if (oldImage.GetType() != eStyleImageType_Image) {
continue;
}
imageLoader->DisassociateRequestFromFrame(oldImage.GetImageData(),
aFrame);
}
}
}
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, (*aNewLayers)) {
// If there is an image in newBG that's not in oldBG, add it.
if (!aOldLayers || i >= aOldLayers->mImageCount ||
!aNewLayers->mLayers[i].mImage.ImageDataEquals(
aOldLayers->mLayers[i].mImage)) {
const nsStyleImage& newImage = aNewLayers->mLayers[i].mImage;
if (newImage.GetType() != eStyleImageType_Image) {
continue;
}
imageLoader->AssociateRequestToFrame(newImage.GetImageData(), aFrame);
}
}
}
// Subclass hook for style post processing
/* virtual */ void
nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
@ -756,50 +806,16 @@ nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
}
}
ImageLoader* imageLoader = PresContext()->Document()->StyleImageLoader();
const nsStyleImageLayers *oldLayers = aOldStyleContext ?
&aOldStyleContext->StyleBackground()->mLayers :
nullptr;
const nsStyleImageLayers *newLayers = &StyleBackground()->mLayers;
AddAndRemoveImageAssociations(this, oldLayers, newLayers);
// If the old context had a background image image and new context
// does not have the same image, clear the image load notifier
// (which keeps the image loading, if it still is) for the frame.
// We want to do this conservatively because some frames paint their
// backgrounds from some other frame's style data, and we don't want
// to clear those notifiers unless we have to. (They'll be reset
// when we paint, although we could miss a notification in that
// interval.)
const nsStyleBackground *oldBG = aOldStyleContext ?
aOldStyleContext->StyleBackground() :
nullptr;
const nsStyleBackground *newBG = StyleBackground();
const nsStyleImageLayers& oldBGLayers = oldBG->mLayers;
const nsStyleImageLayers& newBGLayers = newBG->mLayers;
if (oldBG) {
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, oldBGLayers) {
// If there is an image in oldBG that's not in newBG, drop it.
if (i >= newBGLayers.mImageCount ||
!oldBGLayers.mLayers[i].mImage.ImageDataEquals(newBGLayers.mLayers[i].mImage)) {
const nsStyleImage& oldImage = oldBGLayers.mLayers[i].mImage;
if (oldImage.GetType() != eStyleImageType_Image) {
continue;
}
imageLoader->DisassociateRequestFromFrame(oldImage.GetImageData(),
this);
}
}
}
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, newBGLayers) {
// If there is an image in newBG that's not in oldBG, add it.
if (!oldBG || i >= oldBGLayers.mImageCount ||
!newBGLayers.mLayers[i].mImage.ImageDataEquals(oldBGLayers.mLayers[i].mImage)) {
const nsStyleImage& newImage = newBGLayers.mLayers[i].mImage;
if (newImage.GetType() != eStyleImageType_Image) {
continue;
}
imageLoader->AssociateRequestToFrame(newImage.GetImageData(), this);
}
}
oldLayers = aOldStyleContext ? &aOldStyleContext->StyleSVGReset()->mLayers :
nullptr;
newLayers = &StyleSVGReset()->mLayers;
AddAndRemoveImageAssociations(this, oldLayers, newLayers);
if (aOldStyleContext) {
// If we detect a change on margin, padding or border, we store the old
@ -837,6 +853,7 @@ nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
}
}
ImageLoader* imageLoader = PresContext()->Document()->StyleImageLoader();
imgIRequest *oldBorderImage = aOldStyleContext
? aOldStyleContext->StyleBorder()->GetBorderImageRequest()
: nullptr;

View File

@ -765,6 +765,8 @@ PropertySupportsVariant(nsCSSProperty aPropertyID, uint32_t aVariant)
case eCSSProperty_border_bottom_right_radius:
case eCSSProperty_background_position:
case eCSSProperty_background_size:
case eCSSProperty_mask_position:
case eCSSProperty_mask_size:
case eCSSProperty_grid_auto_columns:
case eCSSProperty_grid_auto_rows:
case eCSSProperty_grid_template_columns:

View File

@ -130,6 +130,7 @@ CSS_KEY(absolute, absolute)
CSS_KEY(active, active)
CSS_KEY(activeborder, activeborder)
CSS_KEY(activecaption, activecaption)
CSS_KEY(add, add)
CSS_KEY(additive, additive)
CSS_KEY(alias, alias)
CSS_KEY(all, all)
@ -255,6 +256,7 @@ CSS_KEY(enabled, enabled)
CSS_KEY(end, end)
CSS_KEY(ethiopic-numeric, ethiopic_numeric)
CSS_KEY(ex, ex)
CSS_KEY(exclude, exclude)
CSS_KEY(exclusion, exclusion)
CSS_KEY(expanded, expanded)
CSS_KEY(extends, extends)
@ -324,6 +326,7 @@ CSS_KEY(inset, inset)
CSS_KEY(inside, inside)
// CSS_KEY(inter-character, inter_character) // TODO see bug 1055672
CSS_KEY(interpolatematrix, interpolatematrix)
CSS_KEY(intersect, intersect)
CSS_KEY(isolate, isolate)
CSS_KEY(invert, invert)
CSS_KEY(italic, italic)
@ -547,6 +550,7 @@ CSS_KEY(styleset, styleset)
CSS_KEY(stylistic, stylistic)
CSS_KEY(sub, sub)
CSS_KEY(subgrid, subgrid)
CSS_KEY(substract, substract)
CSS_KEY(super, super)
CSS_KEY(sw-resize, sw_resize)
CSS_KEY(swash, swash)
@ -774,3 +778,4 @@ CSS_KEY(text-after-edge, text_after_edge)
CSS_KEY(text-before-edge, text_before_edge)
CSS_KEY(use-script, use_script)
CSS_KEY(-moz-crisp-edges, _moz_crisp_edges)

View File

@ -4075,17 +4075,105 @@ CSS_PROP_SVG(
nullptr,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SVGRESET(
CSS_PROP_SHORTHAND(
mask,
mask,
Mask,
CSS_PROPERTY_PARSE_VALUE |
CSS_PROPERTY_CREATES_STACKING_CONTEXT,
CSS_PROPERTY_PARSE_FUNCTION,
"")
CSS_PROP_SVGRESET(
mask-clip,
mask_clip,
MaskClip,
CSS_PROPERTY_PARSE_VALUE_LIST |
CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
"",
VARIANT_HUO,
VARIANT_KEYWORD, // used by list parsing
kImageLayerOriginKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SVGRESET(
mask-composite,
mask_composite,
MaskComposite,
CSS_PROPERTY_PARSE_VALUE_LIST |
CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
"",
VARIANT_KEYWORD, // used by list parsing
kImageLayerCompositeKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SVGRESET(
mask-image,
mask_image,
MaskImage,
CSS_PROPERTY_PARSE_VALUE_LIST |
CSS_PROPERTY_CREATES_STACKING_CONTEXT |
CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
CSS_PROPERTY_START_IMAGE_LOADS,
"",
VARIANT_IMAGE, // used by list parsing
nullptr,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SVGRESET(
mask-mode,
mask_mode,
MaskMode,
CSS_PROPERTY_PARSE_VALUE_LIST |
CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
"",
VARIANT_KEYWORD, // used by list parsing
kImageLayerModeKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SVGRESET(
mask-origin,
mask_origin,
MaskOrigin,
CSS_PROPERTY_PARSE_VALUE_LIST |
CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
"",
VARIANT_KEYWORD, // used by list parsing
kImageLayerOriginKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SVGRESET(
mask-repeat,
mask_repeat,
MaskRepeat,
CSS_PROPERTY_PARSE_FUNCTION |
CSS_PROPERTY_VALUE_LIST_USES_COMMAS,
"",
VARIANT_KEYWORD, // used by list parsing
kImageLayerRepeatKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SVGRESET(
mask-position,
mask_position,
MaskPosition,
CSS_PROPERTY_PARSE_FUNCTION |
CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
CSS_PROPERTY_STORES_CALC,
"",
0,
kImageLayerPositionKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SVGRESET(
mask-size,
mask_size,
MaskSize,
CSS_PROPERTY_PARSE_FUNCTION |
CSS_PROPERTY_VALUE_LIST_USES_COMMAS |
CSS_PROPERTY_VALUE_NONNEGATIVE |
CSS_PROPERTY_STORES_CALC,
"",
0,
kImageLayerSizeKTable,
CSS_PROP_NO_OFFSET,
eStyleAnimType_None)
CSS_PROP_SVGRESET(
mask-type,
mask_type,

View File

@ -930,6 +930,24 @@ const KTableEntry nsCSSProps::kImageLayerSizeKTable[] = {
{ eCSSKeyword_UNKNOWN, -1 }
};
const KTableEntry nsCSSProps::kImageLayerModeKTable[] = {
{ eCSSKeyword_alpha, NS_STYLE_MASK_MODE_ALPHA },
{ eCSSKeyword_luminance, NS_STYLE_MASK_MODE_LUMINANCE },
// FIXME https://bugzilla.mozilla.org/show_bug.cgi?id=1224424
// It's ambigious at mask shorthand parsing while we have both mask-mode:auto
// and mask-size:auto.
{ eCSSKeyword_auto, NS_STYLE_MASK_MODE_AUTO },
{ eCSSKeyword_UNKNOWN, -1 }
};
const KTableEntry nsCSSProps::kImageLayerCompositeKTable[] = {
{ eCSSKeyword_add, NS_STYLE_MASK_COMPOSITE_ADD },
{ eCSSKeyword_substract, NS_STYLE_MASK_COMPOSITE_SUBSTRACT },
{ eCSSKeyword_intersect, NS_STYLE_MASK_COMPOSITE_INTERSECT },
{ eCSSKeyword_exclude, NS_STYLE_MASK_COMPOSITE_EXCLUDE },
{ eCSSKeyword_UNKNOWN, -1 }
};
const KTableEntry nsCSSProps::kBlendModeKTable[] = {
{ eCSSKeyword_normal, NS_STYLE_BLEND_NORMAL },
{ eCSSKeyword_multiply, NS_STYLE_BLEND_MULTIPLY },
@ -2858,6 +2876,21 @@ static const nsCSSProperty gScrollSnapTypeSubpropTable[] = {
eCSSProperty_UNKNOWN
};
static const nsCSSProperty gMaskSubpropTable[] = {
eCSSProperty_mask_image,
eCSSProperty_mask_repeat,
eCSSProperty_mask_position,
eCSSProperty_mask_clip,
eCSSProperty_mask_origin,
eCSSProperty_mask_size,
eCSSProperty_mask_composite,
eCSSProperty_mask_mode,
eCSSProperty_UNKNOWN
};
// FIXME: mask-border tables should be added when we implement
// mask-border properties.
const nsCSSProperty *const
nsCSSProps::kSubpropertyTable[eCSSProperty_COUNT - eCSSProperty_COUNT_no_shorthands] = {
#define CSS_PROP_PUBLIC_OR_PRIVATE(publicname_, privatename_) privatename_

View File

@ -673,6 +673,8 @@ public:
static const KTableEntry kImageLayerRepeatKTable[];
static const KTableEntry kImageLayerRepeatPartKTable[];
static const KTableEntry kImageLayerSizeKTable[];
static const KTableEntry kImageLayerCompositeKTable[];
static const KTableEntry kImageLayerModeKTable[];
static const KTableEntry kBlendModeKTable[];
static const KTableEntry kBorderCollapseKTable[];
static const KTableEntry kBorderColorKTable[];

View File

@ -9694,9 +9694,14 @@ nsRuleNode::ComputeSVGResetData(void* aStartStruct,
}
// mask: url, none, inherit
const nsCSSValue* maskValue = aRuleData->ValueForMask();
if (eCSSUnit_URL == maskValue->GetUnit()) {
svgReset->mMask = maskValue->GetURLValue();
const nsCSSValue* maskValue = aRuleData->ValueForMaskImage();
if (eCSSUnit_List == maskValue->GetUnit() ||
eCSSUnit_ListDep == maskValue->GetUnit()) {
const nsCSSValue& item = maskValue->GetListValue()->mValue;
if (eCSSUnit_URL == item.GetUnit() ||
eCSSUnit_Image == item.GetUnit()) {
svgReset->mMask = item.GetURLValue();
}
} else if (eCSSUnit_None == maskValue->GetUnit() ||
eCSSUnit_Initial == maskValue->GetUnit() ||
eCSSUnit_Unset == maskValue->GetUnit()) {

View File

@ -302,6 +302,11 @@ enum class FillMode : uint32_t;
#define NS_STYLE_IMAGELAYER_SIZE_CONTAIN 0
#define NS_STYLE_IMAGELAYER_SIZE_COVER 1
// Mask mode
#define NS_STYLE_MASK_MODE_ALPHA 0
#define NS_STYLE_MASK_MODE_LUMINANCE 1
#define NS_STYLE_MASK_MODE_AUTO 2
// See nsStyleBackground
#define NS_STYLE_BG_INLINE_POLICY_EACH_BOX 0
#define NS_STYLE_BG_INLINE_POLICY_CONTINUOUS 1
@ -1151,6 +1156,12 @@ enum class FillMode : uint32_t;
#define NS_STYLE_BLEND_COLOR 14
#define NS_STYLE_BLEND_LUMINOSITY 15
// composite
#define NS_STYLE_MASK_COMPOSITE_ADD 0
#define NS_STYLE_MASK_COMPOSITE_SUBSTRACT 1
#define NS_STYLE_MASK_COMPOSITE_INTERSECT 2
#define NS_STYLE_MASK_COMPOSITE_EXCLUDE 3
// See nsStyleText::mControlCharacterVisibility
#define NS_STYLE_CONTROL_CHARACTER_VISIBILITY_HIDDEN 0
#define NS_STYLE_CONTROL_CHARACTER_VISIBILITY_VISIBLE 1

View File

@ -1260,6 +1260,7 @@ nsStyleSVGReset::~nsStyleSVGReset()
}
nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
: mLayers(aSource.mLayers)
{
MOZ_COUNT_CTOR(nsStyleSVGReset);
mStopColor = aSource.mStopColor;
@ -1275,6 +1276,14 @@ nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
mMaskType = aSource.mMaskType;
}
void nsStyleSVGReset::Destroy(nsPresContext* aContext) {
mLayers.UntrackImages(aContext);
this->~nsStyleSVGReset();
aContext->PresShell()->
FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, this);
}
nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const
{
nsChangeHint hint = nsChangeHint(0);
@ -1312,6 +1321,8 @@ nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) cons
NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
}
hint |= mLayers.CalcDifference(aOther.mLayers);
return hint;
}
@ -1333,7 +1344,7 @@ nsStyleSVGPaint::SetType(nsStyleSVGPaintType aType)
mType = aType;
}
nsStyleSVGPaint& nsStyleSVGPaint::operator=(const nsStyleSVGPaint& aOther)
nsStyleSVGPaint& nsStyleSVGPaint::operator=(const nsStyleSVGPaint& aOther)
{
if (this == &aOther)
return *this;
@ -2203,6 +2214,34 @@ nsStyleImage::operator==(const nsStyleImage& aOther) const
// nsStyleImageLayers
//
const nsCSSProperty nsStyleImageLayers::kBackgroundLayerTable[] = {
eCSSProperty_background, // shorthand
eCSSProperty_background_color, // color
eCSSProperty_background_image, // image
eCSSProperty_background_repeat, // repeat
eCSSProperty_background_position, // position
eCSSProperty_background_clip, // clip
eCSSProperty_background_origin, // origin
eCSSProperty_background_size, // size
eCSSProperty_background_attachment, // attachment
eCSSProperty_UNKNOWN, // maskMode
eCSSProperty_UNKNOWN // composite
};
const nsCSSProperty nsStyleImageLayers::kMaskLayerTable[] = {
eCSSProperty_mask, // shorthand
eCSSProperty_UNKNOWN, // color
eCSSProperty_mask_image, // image
eCSSProperty_mask_repeat, // repeat
eCSSProperty_mask_position, // position
eCSSProperty_mask_clip, // clip
eCSSProperty_mask_origin, // origin
eCSSProperty_mask_size, // size
eCSSProperty_UNKNOWN, // attachment
eCSSProperty_mask_mode, // maskMode
eCSSProperty_mask_composite // composite
};
nsStyleImageLayers::nsStyleImageLayers()
: mAttachmentCount(1)
, mClipCount(1)
@ -2211,7 +2250,9 @@ nsStyleImageLayers::nsStyleImageLayers()
, mPositionCount(1)
, mImageCount(1)
, mSizeCount(1)
, mMaskModeCount(1)
, mBlendModeCount(1)
, mCompositeCount(1)
{
MOZ_COUNT_CTOR(nsStyleImageLayers);
mLayers.AppendElement();
@ -2226,7 +2267,9 @@ nsStyleImageLayers::nsStyleImageLayers(const nsStyleImageLayers &aSource)
, mPositionCount(aSource.mPositionCount)
, mImageCount(aSource.mImageCount)
, mSizeCount(aSource.mSizeCount)
, mMaskModeCount(aSource.mMaskModeCount)
, mBlendModeCount(aSource.mBlendModeCount)
, mCompositeCount(aSource.mCompositeCount)
, mLayers(aSource.mLayers) // deep copy
{
MOZ_COUNT_CTOR(nsStyleImageLayers);
@ -2241,10 +2284,84 @@ nsStyleImageLayers::nsStyleImageLayers(const nsStyleImageLayers &aSource)
mPositionCount = std::max(mPositionCount, count);
mImageCount = std::max(mImageCount, count);
mSizeCount = std::max(mSizeCount, count);
mMaskModeCount = std::max(mMaskModeCount, count);
mBlendModeCount = std::max(mBlendModeCount, count);
mCompositeCount = std::max(mCompositeCount, count);
}
}
nsChangeHint
nsStyleImageLayers::CalcDifference(const nsStyleImageLayers& aOther) const
{
nsChangeHint hint = nsChangeHint(0);
const nsStyleImageLayers& moreLayers =
mImageCount > aOther.mImageCount ?
*this : aOther;
const nsStyleImageLayers& lessLayers =
mImageCount > aOther.mImageCount ?
aOther : *this;
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, moreLayers) {
if (i < lessLayers.mImageCount) {
nsChangeHint layerDifference =
moreLayers.mLayers[i].CalcDifference(lessLayers.mLayers[i]);
hint |= layerDifference;
if (layerDifference &&
((moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
(lessLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element))) {
hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
}
} else {
hint |= nsChangeHint_RepaintFrame;
if (moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) {
hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
}
}
}
if (hint) {
return hint;
}
if (mBlendModeCount != aOther.mBlendModeCount ||
mClipCount != aOther.mClipCount ||
mCompositeCount != aOther.mCompositeCount ||
mMaskModeCount != aOther.mMaskModeCount ||
mOriginCount != aOther.mOriginCount ||
mRepeatCount != aOther.mRepeatCount ||
mPositionCount != aOther.mPositionCount ||
mSizeCount != aOther.mSizeCount) {
NS_UpdateHint(hint, nsChangeHint_NeutralChange);
}
return hint;
}
bool
nsStyleImageLayers::HasLayerWithImage() const
{
for (uint32_t i = 0; i < mImageCount; i++) {
if (!mLayers[i].mImage.IsEmpty()) {
return true;
}
}
return false;
}
bool
nsStyleImageLayers::Position::IsInitialValue() const
{
if (mXPosition.mPercent == 0.0 && mXPosition.mLength == 0 &&
mXPosition.mHasPercent && mYPosition.mPercent == 0.0 &&
mYPosition.mLength == 0 && mYPosition.mHasPercent) {
return true;
}
return false;
}
void
nsStyleImageLayers::Position::SetInitialPercentValues(float aPercentVal)
{
@ -2381,7 +2498,9 @@ nsStyleImageLayers::Layer::Layer()
: mClip(NS_STYLE_IMAGELAYER_CLIP_BORDER),
mOrigin(NS_STYLE_IMAGELAYER_ORIGIN_PADDING),
mAttachment(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL),
mBlendMode(NS_STYLE_BLEND_NORMAL)
mBlendMode(NS_STYLE_BLEND_NORMAL),
mComposite(NS_STYLE_MASK_COMPOSITE_ADD),
mMaskMode(NS_STYLE_MASK_MODE_AUTO)
{
mPosition.SetInitialPercentValues(0.0f); // Initial value is "0% 0%"
mImage.SetNull();
@ -2415,7 +2534,9 @@ nsStyleImageLayers::Layer::operator==(const Layer& aOther) const
mBlendMode == aOther.mBlendMode &&
mPosition == aOther.mPosition &&
mSize == aOther.mSize &&
mImage == aOther.mImage;
mImage == aOther.mImage &&
mMaskMode == aOther.mMaskMode &&
mComposite == aOther.mComposite;
}
nsChangeHint
@ -2428,7 +2549,9 @@ nsStyleImageLayers::Layer::CalcDifference(const nsStyleImageLayers::Layer& aOthe
mRepeat != aOther.mRepeat ||
mBlendMode != aOther.mBlendMode ||
mSize != aOther.mSize ||
mImage != aOther.mImage) {
mImage != aOther.mImage ||
mMaskMode != aOther.mMaskMode ||
mComposite != aOther.mComposite) {
hint |= nsChangeHint_RepaintFrame;
}
if (mPosition != aOther.mPosition) {
@ -2473,51 +2596,14 @@ nsStyleBackground::Destroy(nsPresContext* aContext)
nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
{
const nsStyleImageLayers& moreLayers =
mLayers.mImageCount > aOther.mLayers.mImageCount ?
this->mLayers : aOther.mLayers;
const nsStyleImageLayers& lessLayers =
mLayers.mImageCount > aOther.mLayers.mImageCount ?
aOther.mLayers : this->mLayers;
nsChangeHint hint = nsChangeHint(0);
NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, moreLayers) {
if (i < lessLayers.mImageCount) {
nsChangeHint layerDifference = moreLayers.mLayers[i].
CalcDifference(lessLayers.mLayers[i]);
hint |= layerDifference;
if (layerDifference &&
((moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
(lessLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element))) {
hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
}
} else {
hint |= nsChangeHint_RepaintFrame;
if (moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) {
hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
}
}
}
if (mBackgroundColor != aOther.mBackgroundColor) {
hint |= nsChangeHint_RepaintFrame;
}
if (hint) {
return hint;
}
hint |= mLayers.CalcDifference(aOther.mLayers);
if (mLayers.mAttachmentCount != aOther.mLayers.mAttachmentCount ||
mLayers.mClipCount != aOther.mLayers.mClipCount ||
mLayers.mOriginCount != aOther.mLayers.mOriginCount ||
mLayers.mRepeatCount != aOther.mLayers.mRepeatCount ||
mLayers.mPositionCount != aOther.mLayers.mPositionCount ||
mLayers.mSizeCount != aOther.mLayers.mSizeCount) {
return nsChangeHint_NeutralChange;
}
return NS_STYLE_HINT_NONE;
return hint;
}
bool nsStyleBackground::HasFixedBackground() const

View File

@ -405,6 +405,21 @@ struct nsStyleImageLayers {
MOZ_COUNT_DTOR(nsStyleImageLayers);
}
// Indices into kBackgroundLayerTable and kMaskLayerTable
enum {
shorthand = 0,
color,
image,
repeat,
position,
clip,
origin,
size,
attachment,
maskMode,
composite
};
struct Position;
friend struct Position;
struct Position {
@ -414,6 +429,8 @@ struct nsStyleImageLayers {
// Initialize nothing
Position() {}
bool IsInitialValue() const;
// Sets both mXPosition and mYPosition to the given percent value for the
// initial property-value (e.g. 0.0f for "0% 0%", or 0.5f for "50% 50%")
void SetInitialPercentValues(float aPercentVal);
@ -450,6 +467,10 @@ struct nsStyleImageLayers {
};
Dimension mWidth, mHeight;
bool IsInitialValue() const {
return mWidthType == eAuto && mHeightType == eAuto;
}
nscoord ResolveWidthLengthPercentage(const nsSize& aBgPositioningArea) const {
MOZ_ASSERT(mWidthType == eLengthPercentage,
"resolving non-length/percent dimension!");
@ -503,6 +524,11 @@ struct nsStyleImageLayers {
// Initialize nothing
Repeat() {}
bool IsInitialValue() const {
return mXRepeat == NS_STYLE_IMAGELAYER_REPEAT_REPEAT &&
mYRepeat == NS_STYLE_IMAGELAYER_REPEAT_REPEAT;
}
// Initialize to initial values
void SetInitialValues();
@ -528,13 +554,25 @@ struct nsStyleImageLayers {
// This property is used for background layer
// only. For a mask layer, it should always
// be the initial value, which is
// NS_STYLE_BG_ATTACHMENT_SCROLL.
// NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL.
uint8_t mBlendMode; // [reset] See nsStyleConsts.h
// background-only property
// This property is used for background layer
// only. For a mask layer, it should always
// be the initial value, which is
// NS_STYLE_BLEND_NORMAL.
uint8_t mComposite; // [reset] See nsStyleConsts.h
// mask-only property
// This property is used for mask layer only.
// For a background layer, it should always
// be the initial value, which is
// NS_STYLE_COMPOSITE_MODE_ADD.
uint8_t mMaskMode; // [reset] See nsStyleConsts.h
// mask-only property
// This property is used for mask layer only.
// For a background layer, it should always
// be the initial value, which is
// NS_STYLE_MASK_MODE_AUTO.
Repeat mRepeat; // [reset] See nsStyleConsts.h
// Initializes only mImage
@ -579,7 +617,9 @@ struct nsStyleImageLayers {
mPositionCount,
mImageCount,
mSizeCount,
mBlendModeCount;
mMaskModeCount,
mBlendModeCount,
mCompositeCount;
// Layers are stored in an array, matching the top-to-bottom order in
// which they are specified in CSS. The number of layers to be used
@ -604,6 +644,14 @@ struct nsStyleImageLayers {
for (uint32_t i = 0; i < mImageCount; ++i)
mLayers[i].UntrackImages(aContext);
}
nsChangeHint CalcDifference(const nsStyleImageLayers& aOther) const;
bool HasLayerWithImage() const;
static const nsCSSProperty kBackgroundLayerTable[];
static const nsCSSProperty kMaskLayerTable[];
#define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(var_, layers_) \
for (uint32_t var_ = (layers_).mImageCount; var_-- != 0; )
#define NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT_WITH_RANGE(var_, layers_, start_, count_) \
@ -3401,16 +3449,14 @@ struct nsStyleSVGReset
return aContext->PresShell()->
AllocateByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, sz);
}
void Destroy(nsPresContext* aContext) {
this->~nsStyleSVGReset();
aContext->PresShell()->
FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, this);
}
void Destroy(nsPresContext* aContext);
nsChangeHint CalcDifference(const nsStyleSVGReset& aOther) const;
static nsChangeHint MaxDifference() {
return NS_CombineHint(nsChangeHint_UpdateEffects,
NS_CombineHint(nsChangeHint_UpdateOverflow, NS_STYLE_HINT_REFLOW));
return nsChangeHint_UpdateEffects |
nsChangeHint_UpdateOverflow |
nsChangeHint_NeutralChange |
NS_STYLE_HINT_REFLOW;
}
static nsChangeHint DifferenceAlwaysHandledForDescendants() {
// CalcDifference never returns the reflow hints that are sometimes
@ -3428,6 +3474,7 @@ struct nsStyleSVGReset
return mVectorEffect == NS_STYLE_VECTOR_EFFECT_NON_SCALING_STROKE;
}
nsStyleImageLayers mLayers;
nsStyleClipPath mClipPath; // [reset]
nsTArray<nsStyleFilter> mFilters; // [reset]
nsCOMPtr<nsIURI> mMask; // [reset]