зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1560979 - Account for video element's intrinsic size in CanvasRenderingContext2D::DrawImage. r=jib,lsalzman
Differential Revision: https://phabricator.services.mozilla.com/D35782 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
c16328f6e2
Коммит
8a56ba7a99
|
@ -42,7 +42,8 @@ struct ImageCacheEntryData {
|
||||||
: mImage(aOther.mImage),
|
: mImage(aOther.mImage),
|
||||||
mCanvas(aOther.mCanvas),
|
mCanvas(aOther.mCanvas),
|
||||||
mSourceSurface(aOther.mSourceSurface),
|
mSourceSurface(aOther.mSourceSurface),
|
||||||
mSize(aOther.mSize) {}
|
mSize(aOther.mSize),
|
||||||
|
mIntrinsicSize(aOther.mIntrinsicSize) {}
|
||||||
explicit ImageCacheEntryData(const ImageCacheKey& aKey)
|
explicit ImageCacheEntryData(const ImageCacheKey& aKey)
|
||||||
: mImage(aKey.mImage), mCanvas(aKey.mCanvas) {}
|
: mImage(aKey.mImage), mCanvas(aKey.mCanvas) {}
|
||||||
|
|
||||||
|
@ -55,6 +56,7 @@ struct ImageCacheEntryData {
|
||||||
// Value
|
// Value
|
||||||
RefPtr<SourceSurface> mSourceSurface;
|
RefPtr<SourceSurface> mSourceSurface;
|
||||||
IntSize mSize;
|
IntSize mSize;
|
||||||
|
IntSize mIntrinsicSize;
|
||||||
nsExpirationState mState;
|
nsExpirationState mState;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -257,7 +259,8 @@ static already_AddRefed<imgIContainer> GetImageContainer(dom::Element* aImage) {
|
||||||
void CanvasImageCache::NotifyDrawImage(Element* aImage,
|
void CanvasImageCache::NotifyDrawImage(Element* aImage,
|
||||||
HTMLCanvasElement* aCanvas,
|
HTMLCanvasElement* aCanvas,
|
||||||
SourceSurface* aSource,
|
SourceSurface* aSource,
|
||||||
const IntSize& aSize) {
|
const IntSize& aSize,
|
||||||
|
const IntSize& aIntrinsicSize) {
|
||||||
if (!gImageCache) {
|
if (!gImageCache) {
|
||||||
gImageCache = new ImageCache();
|
gImageCache = new ImageCache();
|
||||||
nsContentUtils::RegisterShutdownObserver(
|
nsContentUtils::RegisterShutdownObserver(
|
||||||
|
@ -284,6 +287,7 @@ void CanvasImageCache::NotifyDrawImage(Element* aImage,
|
||||||
gImageCache->AddObject(entry->mData);
|
gImageCache->AddObject(entry->mData);
|
||||||
entry->mData->mSourceSurface = aSource;
|
entry->mData->mSourceSurface = aSource;
|
||||||
entry->mData->mSize = aSize;
|
entry->mData->mSize = aSize;
|
||||||
|
entry->mData->mIntrinsicSize = aIntrinsicSize;
|
||||||
gImageCache->mTotal += entry->mData->SizeInBytes();
|
gImageCache->mTotal += entry->mData->SizeInBytes();
|
||||||
|
|
||||||
AllCanvasImageCacheEntry* allEntry =
|
AllCanvasImageCacheEntry* allEntry =
|
||||||
|
@ -321,7 +325,8 @@ SourceSurface* CanvasImageCache::LookupAllCanvas(Element* aImage) {
|
||||||
|
|
||||||
SourceSurface* CanvasImageCache::LookupCanvas(Element* aImage,
|
SourceSurface* CanvasImageCache::LookupCanvas(Element* aImage,
|
||||||
HTMLCanvasElement* aCanvas,
|
HTMLCanvasElement* aCanvas,
|
||||||
IntSize* aSizeOut) {
|
IntSize* aSizeOut,
|
||||||
|
IntSize* aIntrinsicSizeOut) {
|
||||||
if (!gImageCache) {
|
if (!gImageCache) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -341,6 +346,7 @@ SourceSurface* CanvasImageCache::LookupCanvas(Element* aImage,
|
||||||
|
|
||||||
gImageCache->MarkUsed(entry->mData);
|
gImageCache->MarkUsed(entry->mData);
|
||||||
*aSizeOut = entry->mData->mSize;
|
*aSizeOut = entry->mData->mSize;
|
||||||
|
*aIntrinsicSizeOut = entry->mData->mIntrinsicSize;
|
||||||
return entry->mData->mSourceSurface;
|
return entry->mData->mSourceSurface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,13 @@ class CanvasImageCache {
|
||||||
/**
|
/**
|
||||||
* Notify that image element aImage was drawn to aCanvas element
|
* Notify that image element aImage was drawn to aCanvas element
|
||||||
* using the first frame of aRequest's image. The data for the surface is
|
* using the first frame of aRequest's image. The data for the surface is
|
||||||
* in aSurface, and the image size is in aSize.
|
* in aSurface, and the image size is in aSize. aIntrinsicSize is the size
|
||||||
|
* the surface is intended to be rendered at.
|
||||||
*/
|
*/
|
||||||
static void NotifyDrawImage(dom::Element* aImage,
|
static void NotifyDrawImage(dom::Element* aImage,
|
||||||
dom::HTMLCanvasElement* aCanvas,
|
dom::HTMLCanvasElement* aCanvas,
|
||||||
SourceSurface* aSource,
|
SourceSurface* aSource, const gfx::IntSize& aSize,
|
||||||
const gfx::IntSize& aSize);
|
const gfx::IntSize& aIntrinsicSize);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether aImage has recently been drawn any canvas. If we return
|
* Check whether aImage has recently been drawn any canvas. If we return
|
||||||
|
@ -48,7 +49,8 @@ class CanvasImageCache {
|
||||||
*/
|
*/
|
||||||
static SourceSurface* LookupCanvas(dom::Element* aImage,
|
static SourceSurface* LookupCanvas(dom::Element* aImage,
|
||||||
dom::HTMLCanvasElement* aCanvas,
|
dom::HTMLCanvasElement* aCanvas,
|
||||||
gfx::IntSize* aSizeOut);
|
gfx::IntSize* aSizeOut,
|
||||||
|
gfx::IntSize* aIntrinsicSizeOut);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
|
@ -4288,7 +4288,7 @@ CanvasRenderingContext2D::CachedSurfaceFromElement(Element* aElement) {
|
||||||
res.mCORSUsed = corsmode != imgIRequest::CORS_NONE;
|
res.mCORSUsed = corsmode != imgIRequest::CORS_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.mSize = res.mSourceSurface->GetSize();
|
res.mSize = res.mIntrinsicSize = res.mSourceSurface->GetSize();
|
||||||
res.mPrincipal = principal.forget();
|
res.mPrincipal = principal.forget();
|
||||||
res.mImageRequest = imgRequest.forget();
|
res.mImageRequest = imgRequest.forget();
|
||||||
res.mIsWriteOnly = CheckWriteOnlySecurity(res.mCORSUsed, res.mPrincipal,
|
res.mIsWriteOnly = CheckWriteOnlySecurity(res.mCORSUsed, res.mPrincipal,
|
||||||
|
@ -4331,6 +4331,7 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
|
||||||
|
|
||||||
RefPtr<SourceSurface> srcSurf;
|
RefPtr<SourceSurface> srcSurf;
|
||||||
gfx::IntSize imgSize;
|
gfx::IntSize imgSize;
|
||||||
|
gfx::IntSize intrinsicImgSize;
|
||||||
|
|
||||||
Element* element = nullptr;
|
Element* element = nullptr;
|
||||||
|
|
||||||
|
@ -4363,7 +4364,8 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
|
||||||
SetWriteOnly();
|
SetWriteOnly();
|
||||||
}
|
}
|
||||||
|
|
||||||
imgSize = gfx::IntSize(imageBitmap.Width(), imageBitmap.Height());
|
imgSize = intrinsicImgSize =
|
||||||
|
gfx::IntSize(imageBitmap.Width(), imageBitmap.Height());
|
||||||
} else {
|
} else {
|
||||||
if (aImage.IsHTMLImageElement()) {
|
if (aImage.IsHTMLImageElement()) {
|
||||||
HTMLImageElement* img = &aImage.GetAsHTMLImageElement();
|
HTMLImageElement* img = &aImage.GetAsHTMLImageElement();
|
||||||
|
@ -4378,7 +4380,8 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
|
||||||
element = video;
|
element = video;
|
||||||
}
|
}
|
||||||
|
|
||||||
srcSurf = CanvasImageCache::LookupCanvas(element, mCanvasElement, &imgSize);
|
srcSurf = CanvasImageCache::LookupCanvas(element, mCanvasElement, &imgSize,
|
||||||
|
&intrinsicImgSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsLayoutUtils::DirectDrawInfo drawInfo;
|
nsLayoutUtils::DirectDrawInfo drawInfo;
|
||||||
|
@ -4408,18 +4411,7 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
|
||||||
}
|
}
|
||||||
|
|
||||||
imgSize = res.mSize;
|
imgSize = res.mSize;
|
||||||
|
intrinsicImgSize = res.mIntrinsicSize;
|
||||||
// Scale sw/sh based on aspect ratio
|
|
||||||
if (aImage.IsHTMLVideoElement()) {
|
|
||||||
HTMLVideoElement* video = &aImage.GetAsHTMLVideoElement();
|
|
||||||
int32_t displayWidth = video->VideoWidth();
|
|
||||||
int32_t displayHeight = video->VideoHeight();
|
|
||||||
if (displayWidth == 0 || displayHeight == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
aSw *= (double)imgSize.width / (double)displayWidth;
|
|
||||||
aSh *= (double)imgSize.height / (double)displayHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mCanvasElement) {
|
if (mCanvasElement) {
|
||||||
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement, res.mPrincipal,
|
CanvasUtils::DoDrawImageSecurityCheck(mCanvasElement, res.mPrincipal,
|
||||||
|
@ -4429,7 +4421,8 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
|
||||||
if (res.mSourceSurface) {
|
if (res.mSourceSurface) {
|
||||||
if (res.mImageRequest) {
|
if (res.mImageRequest) {
|
||||||
CanvasImageCache::NotifyDrawImage(element, mCanvasElement,
|
CanvasImageCache::NotifyDrawImage(element, mCanvasElement,
|
||||||
res.mSourceSurface, imgSize);
|
res.mSourceSurface, imgSize,
|
||||||
|
intrinsicImgSize);
|
||||||
}
|
}
|
||||||
srcSurf = res.mSourceSurface;
|
srcSurf = res.mSourceSurface;
|
||||||
} else {
|
} else {
|
||||||
|
@ -4439,8 +4432,10 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
|
||||||
|
|
||||||
if (aOptional_argc == 0) {
|
if (aOptional_argc == 0) {
|
||||||
aSx = aSy = 0.0;
|
aSx = aSy = 0.0;
|
||||||
aDw = aSw = (double)imgSize.width;
|
aSw = (double)imgSize.width;
|
||||||
aDh = aSh = (double)imgSize.height;
|
aSh = (double)imgSize.height;
|
||||||
|
aDw = (double)intrinsicImgSize.width;
|
||||||
|
aDh = (double)intrinsicImgSize.height;
|
||||||
} else if (aOptional_argc == 2) {
|
} else if (aOptional_argc == 2) {
|
||||||
aSx = aSy = 0.0;
|
aSx = aSy = 0.0;
|
||||||
aSw = (double)imgSize.width;
|
aSw = (double)imgSize.width;
|
||||||
|
|
|
@ -7497,6 +7497,7 @@ nsLayoutUtils::SurfaceFromOffscreenCanvas(OffscreenCanvas* aOffscreenCanvas,
|
||||||
|
|
||||||
result.mHasSize = true;
|
result.mHasSize = true;
|
||||||
result.mSize = size;
|
result.mSize = size;
|
||||||
|
result.mIntrinsicSize = size;
|
||||||
result.mIsWriteOnly = aOffscreenCanvas->IsWriteOnly();
|
result.mIsWriteOnly = aOffscreenCanvas->IsWriteOnly();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -7577,6 +7578,7 @@ nsLayoutUtils::SurfaceFromElementResult nsLayoutUtils::SurfaceFromElement(
|
||||||
if (NS_FAILED(rv) || NS_FAILED(rv2)) return result;
|
if (NS_FAILED(rv) || NS_FAILED(rv2)) return result;
|
||||||
}
|
}
|
||||||
result.mSize = IntSize(imgWidth, imgHeight);
|
result.mSize = IntSize(imgWidth, imgHeight);
|
||||||
|
result.mIntrinsicSize = IntSize(imgWidth, imgHeight);
|
||||||
|
|
||||||
if (!noRasterize || imgContainer->GetType() == imgIContainer::TYPE_RASTER) {
|
if (!noRasterize || imgContainer->GetType() == imgIContainer::TYPE_RASTER) {
|
||||||
if (aSurfaceFlags & SFE_WANT_IMAGE_SURFACE) {
|
if (aSurfaceFlags & SFE_WANT_IMAGE_SURFACE) {
|
||||||
|
@ -7674,6 +7676,7 @@ nsLayoutUtils::SurfaceFromElementResult nsLayoutUtils::SurfaceFromElement(
|
||||||
|
|
||||||
result.mHasSize = true;
|
result.mHasSize = true;
|
||||||
result.mSize = size;
|
result.mSize = size;
|
||||||
|
result.mIntrinsicSize = size;
|
||||||
result.mPrincipal = aElement->NodePrincipal();
|
result.mPrincipal = aElement->NodePrincipal();
|
||||||
result.mHadCrossOriginRedirects = false;
|
result.mHadCrossOriginRedirects = false;
|
||||||
result.mIsWriteOnly = aElement->IsWriteOnly();
|
result.mIsWriteOnly = aElement->IsWriteOnly();
|
||||||
|
@ -7721,6 +7724,8 @@ nsLayoutUtils::SurfaceFromElementResult nsLayoutUtils::SurfaceFromElement(
|
||||||
result.mCORSUsed = aElement->GetCORSMode() != CORS_NONE;
|
result.mCORSUsed = aElement->GetCORSMode() != CORS_NONE;
|
||||||
result.mHasSize = true;
|
result.mHasSize = true;
|
||||||
result.mSize = result.mLayersImage->GetSize();
|
result.mSize = result.mLayersImage->GetSize();
|
||||||
|
result.mIntrinsicSize =
|
||||||
|
gfx::IntSize(aElement->VideoWidth(), aElement->VideoHeight());
|
||||||
result.mPrincipal = principal.forget();
|
result.mPrincipal = principal.forget();
|
||||||
result.mHadCrossOriginRedirects = aElement->HadCrossOriginRedirects();
|
result.mHadCrossOriginRedirects = aElement->HadCrossOriginRedirects();
|
||||||
result.mIsWriteOnly = CanvasUtils::CheckWriteOnlySecurity(
|
result.mIsWriteOnly = CanvasUtils::CheckWriteOnlySecurity(
|
||||||
|
|
|
@ -2155,6 +2155,8 @@ class nsLayoutUtils {
|
||||||
|
|
||||||
/* The size of the surface */
|
/* The size of the surface */
|
||||||
mozilla::gfx::IntSize mSize;
|
mozilla::gfx::IntSize mSize;
|
||||||
|
/* The size the surface is intended to be rendered at */
|
||||||
|
mozilla::gfx::IntSize mIntrinsicSize;
|
||||||
/* The principal associated with the element whose surface was returned.
|
/* The principal associated with the element whose surface was returned.
|
||||||
If there is a surface, this will never be null. */
|
If there is a surface, this will never be null. */
|
||||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
[MediaStreamTrack-MediaElement-disabled-video-is-black.https.html]
|
|
||||||
[Tests that a disabled video track in a MediaStream is rendered as blackness]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[A disabled video track is rendered as blackness]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче