mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-14 02:31:59 +00:00
Bug 686281 - Implement CSS mask style; r=dbaron.
This commit is contained in:
parent
538b854ad1
commit
577578571f
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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_
|
||||
|
@ -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[];
|
||||
|
@ -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()) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
Loading…
Reference in New Issue
Block a user