mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 03:15:11 +00:00
Bug 1783069 - Make aspect-ratio work on <video> properly. r=boris,Oriol,layout-reviewers
See https://github.com/w3c/csswg-drafts/issues/7524 for discussion. This matches what we do for images. Differential Revision: https://phabricator.services.mozilla.com/D153664
This commit is contained in:
parent
a5d1294a68
commit
c94712abf1
@ -397,7 +397,7 @@ nscoord nsVideoFrame::GetMinISize(gfxContext* aRenderingContext) {
|
||||
// therefore must match the function's return value.
|
||||
DISPLAY_MIN_INLINE_SIZE(this, result);
|
||||
// This call handles size-containment
|
||||
nsSize size = GetVideoIntrinsicSize();
|
||||
nsSize size = GetIntrinsicSize().ToSize().valueOr(nsSize());
|
||||
result = GetWritingMode().IsVertical() ? size.height : size.width;
|
||||
return result;
|
||||
}
|
||||
@ -424,7 +424,7 @@ AspectRatio nsVideoFrame::GetIntrinsicRatio() const {
|
||||
return AspectRatio();
|
||||
}
|
||||
|
||||
HTMLVideoElement* element = static_cast<HTMLVideoElement*>(GetContent());
|
||||
auto* element = static_cast<HTMLVideoElement*>(GetContent());
|
||||
if (Maybe<CSSIntSize> size = element->GetVideoSize()) {
|
||||
return AspectRatio::FromSize(*size);
|
||||
}
|
||||
@ -435,14 +435,22 @@ AspectRatio nsVideoFrame::GetIntrinsicRatio() const {
|
||||
}
|
||||
}
|
||||
|
||||
if (StylePosition()->mAspectRatio.HasRatio()) {
|
||||
return AspectRatio();
|
||||
}
|
||||
|
||||
return AspectRatio::FromSize(kFallbackIntrinsicSizeInPixels);
|
||||
}
|
||||
|
||||
bool nsVideoFrame::ShouldDisplayPoster() const {
|
||||
if (!HasVideoElement()) return false;
|
||||
if (!HasVideoElement()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HTMLVideoElement* element = static_cast<HTMLVideoElement*>(GetContent());
|
||||
if (element->GetPlayedOrSeeked() && HasVideoData()) return false;
|
||||
auto* element = static_cast<HTMLVideoElement*>(GetContent());
|
||||
if (element->GetPlayedOrSeeked() && HasVideoData()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIImageLoadingContent> imgContent = do_QueryInterface(mPosterImage);
|
||||
NS_ENSURE_TRUE(imgContent, false);
|
||||
@ -461,48 +469,53 @@ bool nsVideoFrame::ShouldDisplayPoster() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
nsSize nsVideoFrame::GetVideoIntrinsicSize() const {
|
||||
IntrinsicSize nsVideoFrame::GetIntrinsicSize() {
|
||||
const auto containAxes = StyleDisplay()->GetContainSizeAxes();
|
||||
const auto isVideo = HasVideoElement();
|
||||
// Intrinsic size will be given by contain-intrinsic-size if the element is
|
||||
// size-contained. If both axes have containment, ContainSize() will ignore
|
||||
// the fallback size argument, so we can just pass 0,0 or whatever.
|
||||
// size-contained. If both axes have containment, ContainIntrinsicSize() will
|
||||
// ignore the fallback size argument, so we can just pass no intrinsic size,
|
||||
// or whatever.
|
||||
if (containAxes.IsBoth()) {
|
||||
return containAxes.ContainSize({}, *this);
|
||||
}
|
||||
|
||||
// An audio element with no "controls" attribute, distinguished by the last
|
||||
// and only child being the control, falls back to 0,0.
|
||||
if (!isVideo && !mFrames.LastChild()) {
|
||||
return containAxes.ContainSize({}, *this);
|
||||
return containAxes.ContainIntrinsicSize({}, *this);
|
||||
}
|
||||
|
||||
if (!isVideo) {
|
||||
return containAxes.ContainSize(kFallbackIntrinsicSize, *this);
|
||||
// An audio element with no "controls" attribute, distinguished by the last
|
||||
// and only child being the control, falls back to no intrinsic size.
|
||||
if (!mFrames.LastChild()) {
|
||||
return containAxes.ContainIntrinsicSize({}, *this);
|
||||
}
|
||||
|
||||
return containAxes.ContainIntrinsicSize(
|
||||
IntrinsicSize(kFallbackIntrinsicSize), *this);
|
||||
}
|
||||
|
||||
HTMLVideoElement* element = static_cast<HTMLVideoElement*>(GetContent());
|
||||
auto* element = static_cast<HTMLVideoElement*>(GetContent());
|
||||
if (Maybe<CSSIntSize> size = element->GetVideoSize()) {
|
||||
return containAxes.ContainSize(CSSPixel::ToAppUnits(*size), *this);
|
||||
return containAxes.ContainIntrinsicSize(
|
||||
IntrinsicSize(CSSPixel::ToAppUnits(*size)), *this);
|
||||
}
|
||||
|
||||
if (ShouldDisplayPoster()) {
|
||||
if (Maybe<nsSize> imgSize = PosterImageSize()) {
|
||||
return containAxes.ContainSize(*imgSize, *this);
|
||||
return containAxes.ContainIntrinsicSize(IntrinsicSize(*imgSize), *this);
|
||||
}
|
||||
}
|
||||
return containAxes.ContainSize(kFallbackIntrinsicSize, *this);
|
||||
}
|
||||
|
||||
IntrinsicSize nsVideoFrame::GetIntrinsicSize() {
|
||||
return IntrinsicSize(GetVideoIntrinsicSize());
|
||||
if (StylePosition()->mAspectRatio.HasRatio()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return containAxes.ContainIntrinsicSize(IntrinsicSize(kFallbackIntrinsicSize),
|
||||
*this);
|
||||
}
|
||||
|
||||
void nsVideoFrame::UpdatePosterSource(bool aNotify) {
|
||||
NS_ASSERTION(HasVideoElement(), "Only call this on <video> elements.");
|
||||
HTMLVideoElement* element = static_cast<HTMLVideoElement*>(GetContent());
|
||||
|
||||
if (element->HasAttr(kNameSpaceID_None, nsGkAtoms::poster) &&
|
||||
if (element->HasAttr(nsGkAtoms::poster) &&
|
||||
!element->AttrValueIs(kNameSpaceID_None, nsGkAtoms::poster,
|
||||
nsGkAtoms::_empty, eIgnoreCase)) {
|
||||
nsAutoString posterStr;
|
||||
|
@ -47,7 +47,6 @@ class nsVideoFrame final : public nsContainerFrame,
|
||||
const Maybe<OnNonvisible>& aNonvisibleAction = Nothing()) override;
|
||||
|
||||
/* get the size of the video's display */
|
||||
nsSize GetVideoIntrinsicSize() const;
|
||||
mozilla::IntrinsicSize GetIntrinsicSize() override;
|
||||
mozilla::AspectRatio GetIntrinsicRatio() const override;
|
||||
SizeComputationResult ComputeSize(
|
||||
|
@ -39,10 +39,7 @@ t.step(function() {
|
||||
video.setAttribute("height", "100");
|
||||
video.src = getVideoURI('/media/2x2-green');
|
||||
document.body.appendChild(video);
|
||||
// Videos default to a size of 300x150px and calculate their aspect ratio
|
||||
// based on that before the video is loaded. So this should be 2, ignoring
|
||||
// the 2.5 that it would be based on the attributes.
|
||||
assert_ratio(video, 2);
|
||||
assert_ratio(video, 2.5);
|
||||
|
||||
video.onloadeddata = t.step_func_done(function() {
|
||||
// When loaded this video is square.
|
||||
@ -50,6 +47,22 @@ t.step(function() {
|
||||
});
|
||||
}, "aspect ratio for regular video");
|
||||
|
||||
// Same but with auto width.
|
||||
t.step(function() {
|
||||
video = document.createElement("video");
|
||||
video.setAttribute("width", "250");
|
||||
video.setAttribute("height", "100");
|
||||
video.style.width = "auto";
|
||||
video.src = getVideoURI('/media/2x2-green');
|
||||
document.body.appendChild(video);
|
||||
assert_ratio(video, 2.5);
|
||||
|
||||
video.onloadeddata = t.step_func_done(function() {
|
||||
// When loaded this video is square.
|
||||
assert_ratio(video, 1);
|
||||
});
|
||||
}, "aspect ratio for regular video with width: auto and height: auto");
|
||||
|
||||
test_computed_style("10", "20", "auto 10 / 20");
|
||||
test_computed_style("0.5", "1.5", "auto 0.5 / 1.5");
|
||||
test_computed_style("0", "1", "auto 0 / 1");
|
||||
|
Loading…
Reference in New Issue
Block a user