Bug 624647 part 0: Don't use ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT flag if 'object-fit' and/or 'object-position' might make our drawing overflow. r=roc

This commit is contained in:
Daniel Holbert 2014-11-14 16:45:23 -08:00
parent 0e3053af71
commit 6c33817dd5
4 changed files with 95 additions and 5 deletions

View File

@ -31,6 +31,7 @@
#include "nsStyleContext.h"
#include "nsStyleConsts.h"
#include "nsStyleCoord.h"
#include "nsStyleUtil.h"
#include "nsTransform2D.h"
#include "nsImageMap.h"
#include "nsIIOService.h"
@ -1528,8 +1529,12 @@ nsImageFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
DisplayBorderBackgroundOutline(aBuilder, aLists);
uint32_t clipFlags =
nsStyleUtil::ObjectPropsMightCauseOverflow(StylePosition()) ?
0 : DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT;
DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
clip(aBuilder, this, DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT);
clip(aBuilder, this, clipFlags);
if (mComputedSize.width != 0 && mComputedSize.height != 0) {
nsCOMPtr<nsIImageLoadingContent> imageLoader = do_QueryInterface(mContent);

View File

@ -25,6 +25,7 @@
#include "ImageContainer.h"
#include "ImageLayers.h"
#include "nsContentList.h"
#include "nsStyleUtil.h"
#include <algorithm>
using namespace mozilla;
@ -432,10 +433,24 @@ nsVideoFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
DisplayBorderBackgroundOutline(aBuilder, aLists);
DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
clip(aBuilder, this, DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT);
const bool shouldDisplayPoster = ShouldDisplayPoster();
if (HasVideoElement() && !ShouldDisplayPoster()) {
// NOTE: If we're displaying a poster image (instead of video data), we can
// trust the nsImageFrame to constrain its drawing to its content rect
// (which happens to be the same as our content rect).
uint32_t clipFlags;
if (shouldDisplayPoster ||
!nsStyleUtil::ObjectPropsMightCauseOverflow(StylePosition())) {
clipFlags =
DisplayListClipState::ASSUME_DRAWING_RESTRICTED_TO_CONTENT_RECT;
} else {
clipFlags = 0;
}
DisplayListClipState::AutoClipContainingBlockDescendantsToContentBox
clip(aBuilder, this, clipFlags);
if (HasVideoElement() && !shouldDisplayPoster) {
aLists.Content()->AppendNewToTop(
new (aBuilder) nsDisplayVideo(aBuilder, this));
}
@ -446,7 +461,7 @@ nsVideoFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
for (nsIFrame *child = mFrames.FirstChild();
child;
child = child->GetNextSibling()) {
if (child->GetContent() != mPosterImage || ShouldDisplayPoster()) {
if (child->GetContent() != mPosterImage || shouldDisplayPoster) {
child->BuildDisplayListForStackingContext(aBuilder,
aDirtyRect - child->GetOffsetTo(this),
aLists.Content());

View File

@ -10,6 +10,7 @@
#include "nsCSSProps.h"
#include "nsRuleNode.h"
#include "nsROCSSPrimitiveValue.h"
#include "nsStyleStruct.h"
#include "nsIContentPolicy.h"
#include "nsIContentSecurityPolicy.h"
#include "nsIURI.h"
@ -619,6 +620,57 @@ nsStyleUtil::IsFlexBasisMainSize(const nsStyleCoord& aFlexBasis,
return aFlexBasis.GetIntValue() == NS_STYLE_FLEX_BASIS_MAIN_SIZE;
}
// For a replaced element whose concrete object size is no larger than the
// element's content-box, this method checks whether the given
// "object-position" coordinate might cause overflow in its dimension.
typedef nsStyleBackground::Position::PositionCoord PositionCoord;
static bool
ObjectPositionCoordMightCauseOverflow(const PositionCoord& aCoord)
{
// Any nonzero length in "object-position" can push us to overflow
// (particularly if our concrete object size is exactly the same size as the
// replaced element's content-box).
if (aCoord.mLength != 0) {
return true;
}
// Percentages are interpreted as a fraction of the extra space. So,
// percentages in the 0-100% range are safe, but values outside of that
// range could cause overflow.
if (aCoord.mHasPercent &&
(aCoord.mPercent < 0.0f || aCoord.mPercent > 1.0f)) {
return true;
}
return false;
}
/* static */ bool
nsStyleUtil::ObjectPropsMightCauseOverflow(const nsStylePosition* aStylePos)
{
auto objectFit = aStylePos->mObjectFit;
// "object-fit: cover" & "object-fit: none" can give us a render rect that's
// larger than our container element's content-box.
if (objectFit == NS_STYLE_OBJECT_FIT_COVER ||
objectFit == NS_STYLE_OBJECT_FIT_NONE) {
return true;
}
// (All other object-fit values produce a concrete object size that's no larger
// than the constraint region.)
// Check each of our "object-position" coords to see if it could cause
// overflow in its dimension:
const nsStyleBackground::Position& objectPosistion = aStylePos->mObjectPosition;
if (ObjectPositionCoordMightCauseOverflow(objectPosistion.mXPosition) ||
ObjectPositionCoordMightCauseOverflow(objectPosistion.mYPosition)) {
return true;
}
return false;
}
/* static */ bool
nsStyleUtil::CSPAllowsInlineStyle(nsIContent* aContent,
nsIPrincipal* aPrincipal,

View File

@ -20,6 +20,7 @@ class nsIURI;
struct gfxFontFeature;
struct gfxAlternateValue;
struct nsCSSValueList;
struct nsStylePosition;
// Style utility functions
class nsStyleUtil {
@ -130,6 +131,23 @@ public:
static bool IsFlexBasisMainSize(const nsStyleCoord& aFlexBasis,
bool aIsMainAxisHorizontal);
/**
* Returns true if our object-fit & object-position properties might cause
* a replaced element's contents to overflow its content-box (requiring
* clipping), or false if we can be sure that this won't happen.
*
* This lets us optimize by skipping clipping when we can tell it's
* unnecessary (particularly with the default values of these properties).
*
* @param aStylePos The nsStylePosition whose object-fit & object-position
* properties should be checked for potential overflow.
* @return false if we can be sure that the object-fit & object-position
* properties on 'aStylePos' cannot cause a replaced element's
* contents to overflow its content-box. Otherwise (if overflow is
* is possible), returns true.
*/
static bool ObjectPropsMightCauseOverflow(const nsStylePosition* aStylePos);
/*
* Does this principal have a CSP that blocks the application of
* inline styles? Returns false if application of the style should