diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-05-15 10:20:33 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-05-15 10:28:57 +0000 |
commit | d17ea114e5ef69ad5d5d7413280a13e6428098aa (patch) | |
tree | 2c01a75df69f30d27b1432467cfe7c1467a498da /chromium/third_party/blink/renderer/core/layout/layout_video.cc | |
parent | 8c5c43c7b138c9b4b0bf56d946e61d3bbc111bec (diff) | |
download | qtwebengine-chromium-d17ea114e5ef69ad5d5d7413280a13e6428098aa.tar.gz |
BASELINE: Update Chromium to 67.0.3396.47
Change-Id: Idcb1341782e417561a2473eeecc82642dafda5b7
Reviewed-by: Michal Klocek <michal.klocek@qt.io>
Diffstat (limited to 'chromium/third_party/blink/renderer/core/layout/layout_video.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/layout/layout_video.cc | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/core/layout/layout_video.cc b/chromium/third_party/blink/renderer/core/layout/layout_video.cc new file mode 100644 index 00000000000..db9b951b1d6 --- /dev/null +++ b/chromium/third_party/blink/renderer/core/layout/layout_video.cc @@ -0,0 +1,240 @@ +/* + * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "third_party/blink/renderer/core/layout/layout_video.h" + +#include "third_party/blink/public/platform/web_layer.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/html/media/html_video_element.h" +#include "third_party/blink/renderer/core/html_names.h" +#include "third_party/blink/renderer/core/layout/layout_block_flow.h" +#include "third_party/blink/renderer/core/layout/layout_full_screen.h" +#include "third_party/blink/renderer/core/paint/video_painter.h" + +namespace blink { + +using namespace HTMLNames; + +LayoutVideo::LayoutVideo(HTMLVideoElement* video) : LayoutMedia(video) { + SetIntrinsicSize(CalculateIntrinsicSize()); +} + +LayoutVideo::~LayoutVideo() = default; + +LayoutSize LayoutVideo::DefaultSize() { + return LayoutSize(kDefaultWidth, kDefaultHeight); +} + +void LayoutVideo::IntrinsicSizeChanged() { + if (VideoElement()->ShouldDisplayPosterImage()) + LayoutMedia::IntrinsicSizeChanged(); + UpdateIntrinsicSize(); +} + +void LayoutVideo::UpdateIntrinsicSize() { + LayoutSize size = CalculateIntrinsicSize(); + size.Scale(Style()->EffectiveZoom()); + + // Never set the element size to zero when in a media document. + if (size.IsEmpty() && GetNode()->ownerDocument() && + GetNode()->ownerDocument()->IsMediaDocument()) + return; + + if (size == IntrinsicSize()) + return; + + SetIntrinsicSize(size); + SetPreferredLogicalWidthsDirty(); + SetNeedsLayoutAndFullPaintInvalidation( + LayoutInvalidationReason::kSizeChanged); +} + +LayoutSize LayoutVideo::CalculateIntrinsicSize() { + HTMLVideoElement* video = VideoElement(); + + // Spec text from 4.8.6 + // + // The intrinsic width of a video element's playback area is the intrinsic + // width of the video resource, if that is available; otherwise it is the + // intrinsic width of the poster frame, if that is available; otherwise it is + // 300 CSS pixels. + // + // The intrinsic height of a video element's playback area is the intrinsic + // height of the video resource, if that is available; otherwise it is the + // intrinsic height of the poster frame, if that is available; otherwise it is + // 150 CSS pixels. + WebMediaPlayer* web_media_player = MediaElement()->GetWebMediaPlayer(); + if (web_media_player && + video->getReadyState() >= HTMLVideoElement::kHaveMetadata) { + IntSize size = web_media_player->NaturalSize(); + if (!size.IsEmpty()) + return LayoutSize(size); + } + + if (video->ShouldDisplayPosterImage() && !cached_image_size_.IsEmpty() && + !ImageResource()->ErrorOccurred()) + return cached_image_size_; + + return DefaultSize(); +} + +void LayoutVideo::ImageChanged(WrappedImagePtr new_image, + CanDeferInvalidation defer, + const IntRect* rect) { + LayoutMedia::ImageChanged(new_image, defer, rect); + + // Cache the image intrinsic size so we can continue to use it to draw the + // image correctly even if we know the video intrinsic size but aren't able to + // draw video frames yet (we don't want to scale the poster to the video size + // without keeping aspect ratio). + if (VideoElement()->ShouldDisplayPosterImage()) + cached_image_size_ = IntrinsicSize(); + + // The intrinsic size is now that of the image, but in case we already had the + // intrinsic size of the video we call this here to restore the video size. + UpdateIntrinsicSize(); +} + +bool LayoutVideo::ShouldDisplayVideo() const { + return !VideoElement()->ShouldDisplayPosterImage(); +} + +void LayoutVideo::PaintReplaced(const PaintInfo& paint_info, + const LayoutPoint& paint_offset) const { + VideoPainter(*this).PaintReplaced(paint_info, paint_offset); +} + +void LayoutVideo::UpdateLayout() { + UpdatePlayer(); + LayoutMedia::UpdateLayout(); +} + +HTMLVideoElement* LayoutVideo::VideoElement() const { + return ToHTMLVideoElement(GetNode()); +} + +void LayoutVideo::UpdateFromElement() { + LayoutMedia::UpdateFromElement(); + UpdatePlayer(); + + // If the DisplayMode of the video changed, then we need to paint. + SetShouldDoFullPaintInvalidation(); +} + +void LayoutVideo::UpdatePlayer() { + UpdateIntrinsicSize(); + + WebMediaPlayer* media_player = MediaElement()->GetWebMediaPlayer(); + if (!media_player) + return; + + if (!VideoElement()->InActiveDocument()) + return; + + VideoElement()->SetNeedsCompositingUpdate(); +} + +LayoutUnit LayoutVideo::ComputeReplacedLogicalWidth( + ShouldComputePreferred should_compute_preferred) const { + return LayoutReplaced::ComputeReplacedLogicalWidth(should_compute_preferred); +} + +LayoutUnit LayoutVideo::ComputeReplacedLogicalHeight( + LayoutUnit estimated_used_width) const { + return LayoutReplaced::ComputeReplacedLogicalHeight(estimated_used_width); +} + +LayoutUnit LayoutVideo::MinimumReplacedHeight() const { + return LayoutReplaced::MinimumReplacedHeight(); +} + +LayoutRect LayoutVideo::ReplacedContentRect() const { + if (ShouldDisplayVideo()) { + // Video codecs may need to restart from an I-frame when the output is + // resized. Round size in advance to avoid 1px snap difference. + // TODO(trchen): The way of rounding is different from LayoutEmbeddedContent + // just to match existing behavior. This is probably a bug and We should + // unify it with LayoutEmbeddedContent. + return LayoutRect(PixelSnappedIntRect(ComputeObjectFit())); + } + // If we are displaying the poster image no pre-rounding is needed, but the + // size of the image should be used for fitting instead. + return ComputeObjectFit(&cached_image_size_); +} + +bool LayoutVideo::SupportsAcceleratedRendering() const { + return !!MediaElement()->PlatformLayer(); +} + +static const LayoutBlock* LayoutObjectPlaceholder( + const LayoutObject* layout_object) { + LayoutObject* parent = layout_object->Parent(); + if (!parent) + return nullptr; + + LayoutFullScreen* full_screen = + parent->IsLayoutFullScreen() ? ToLayoutFullScreen(parent) : nullptr; + if (!full_screen) + return nullptr; + + return full_screen->Placeholder(); +} + +LayoutUnit LayoutVideo::OffsetLeft(const Element* parent) const { + if (const LayoutBlock* block = LayoutObjectPlaceholder(this)) + return block->OffsetLeft(parent); + return LayoutMedia::OffsetLeft(parent); +} + +LayoutUnit LayoutVideo::OffsetTop(const Element* parent) const { + if (const LayoutBlock* block = LayoutObjectPlaceholder(this)) + return block->OffsetTop(parent); + return LayoutMedia::OffsetTop(parent); +} + +LayoutUnit LayoutVideo::OffsetWidth() const { + if (const LayoutBlock* block = LayoutObjectPlaceholder(this)) + return block->OffsetWidth(); + return LayoutMedia::OffsetWidth(); +} + +LayoutUnit LayoutVideo::OffsetHeight() const { + if (const LayoutBlock* block = LayoutObjectPlaceholder(this)) + return block->OffsetHeight(); + return LayoutMedia::OffsetHeight(); +} + +CompositingReasons LayoutVideo::AdditionalCompositingReasons() const { + HTMLMediaElement* element = ToHTMLMediaElement(GetNode()); + if (element->IsFullscreen() && element->UsesOverlayFullscreenVideo()) + return CompositingReason::kVideo; + + if (ShouldDisplayVideo() && SupportsAcceleratedRendering()) + return CompositingReason::kVideo; + + return CompositingReason::kNone; +} + +} // namespace blink |