Bug 1423850 - Take into account video's rotation metadata at context.drawImage() with <video> r=gfx-reviewers,bradwerth

Rotated video for reftest is re-used from bug1228601-video-rotation-90.html

Differential Revision: https://phabricator.services.mozilla.com/D140353
This commit is contained in:
sotaro 2022-03-18 00:01:02 +00:00
parent 0b222551dc
commit fe0ee34bf8
4 changed files with 88 additions and 1 deletions

View File

@ -4538,6 +4538,33 @@ SurfaceFromElementResult CanvasRenderingContext2D::CachedSurfaceFromElement(
return res;
}
static void SwapScaleWidthHeightForRotation(gfx::Rect& aRect,
VideoInfo::Rotation aDegrees) {
if (aDegrees == VideoInfo::Rotation::kDegree_90 ||
aDegrees == VideoInfo::Rotation::kDegree_270) {
std::swap(aRect.width, aRect.height);
}
}
static Matrix ComputeRotationMatrix(gfxFloat aRotatedWidth,
gfxFloat aRotatedHeight,
VideoInfo::Rotation aDegrees) {
Matrix shiftVideoCenterToOrigin;
if (aDegrees == VideoInfo::Rotation::kDegree_90 ||
aDegrees == VideoInfo::Rotation::kDegree_270) {
shiftVideoCenterToOrigin =
Matrix::Translation(-aRotatedHeight / 2.0, -aRotatedWidth / 2.0);
} else {
shiftVideoCenterToOrigin =
Matrix::Translation(-aRotatedWidth / 2.0, -aRotatedHeight / 2.0);
}
Matrix rotation = Matrix::Rotation(gfx::Float(aDegrees / 180.0 * M_PI));
Matrix shiftLeftTopToOrigin =
Matrix::Translation(aRotatedWidth / 2.0, aRotatedHeight / 2.0);
return shiftVideoCenterToOrigin * rotation * shiftLeftTopToOrigin;
}
// drawImage(in HTMLImageElement image, in float dx, in float dy);
// -- render image from 0,0 at dx,dy top-left coords
// drawImage(in HTMLImageElement image, in float dx, in float dy, in float dw,
@ -4776,10 +4803,37 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
if (!IsTargetValid() || !tempTarget) {
return;
}
VideoInfo::Rotation rotationDeg = VideoInfo::Rotation::kDegree_0;
if (HTMLVideoElement* video = HTMLVideoElement::FromNodeOrNull(element)) {
rotationDeg = video->RotationDegrees();
}
gfx::Rect destRect(aDx, aDy, aDw, aDh);
Matrix transform;
if (rotationDeg != VideoInfo::Rotation::kDegree_0) {
Matrix preTransform = ComputeRotationMatrix(aDw, aDh, rotationDeg);
transform = preTransform * Matrix::Translation(aDx, aDy);
SwapScaleWidthHeightForRotation(destRect, rotationDeg);
// When rotation exists, aDx, aDy is handled by transform, Since aDest.x
// aDest.y handling of DrawSurface() does not care about the rotation.
destRect.x = 0;
destRect.y = 0;
}
Matrix currentTransform = tempTarget->GetTransform();
transform *= currentTransform;
tempTarget->SetTransform(transform);
tempTarget->DrawSurface(
srcSurf, gfx::Rect(aDx, aDy, aDw, aDh), sourceRect,
srcSurf, destRect, sourceRect,
DrawSurfaceOptions(samplingFilter, SamplingBounds::UNBOUNDED),
DrawOptions(CurrentState().globalAlpha, op, antialiasMode));
tempTarget->SetTransform(currentTransform);
} else {
DrawDirectlyToCanvas(drawInfo, &bounds, gfx::Rect(aDx, aDy, aDw, aDh),
gfx::Rect(aSx, aSy, aSw, aSh), imgSize);

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head><script>
function done() {
let video = document.querySelector("video");
let canvas = document.querySelector("canvas");
let context = canvas.getContext("2d");
context.drawImage(video, 30, 50, video.videoWidth, video.videoHeight);
document.documentElement.removeAttribute("class");
}
</script></head>
<body bgcolor="gray">
<video src="video_rotated.mp4" onended="done()" autoplay="true"></video>
<canvas width="60" height="100"></canvas>
</body>
</html>

View File

@ -0,0 +1,16 @@
<!DOCTYPE html>
<html class="reftest-wait">
<head><script>
function done() {
let video = document.querySelector("video");
let canvas = document.querySelector("canvas");
let context = canvas.getContext("2d");
context.drawImage(video, 30, 50, video.videoWidth, video.videoHeight);
document.documentElement.removeAttribute("class");
}
</script></head>
<body bgcolor="gray">
<video src="video_rotation_90.mp4" onended="done()" autoplay="true"></video>
<canvas width="60" height="100"></canvas>
</body>
</html>

View File

@ -63,6 +63,7 @@ pref(permissions.default.image,2) HTTP == bug1196784-with-srcset.html bug1196784
# Test video with rotation information can be rotated.
skip-if(geckoview&&debug) == bug1228601-video-rotation-90.html bug1228601-video-rotated-ref.html # bug 1558285 for GV debug
skip-if(geckoview&&debug) fuzzy(0-1,0-30) == bug1423850-canvas-video-rotation-90.html bug1423850-canvas-video-rotated-ref.html # bug 1558285 for GV debug
== bug1512297.html bug1512297-ref.html