Bug 1965114 part 2: Add a new imgIContainer.intrinsicSize attr as a shorthand for getting width & height. r=tnikkel

This is mostly just a convenience shorthand to avoid running the same
boilerplate/error-checking code in the implementation of the 'width' and
'height' attributes, for the benefit of callers that need both sizes.  But,
beyond that convenience: this also lets us elegantly express the case where an
image simply lacks an intrinsic width and/or height (not due to any error, but
simply because it's e.g. an SVG that has no preferred size in either or both of
its axes).  This is a state we'll need to be able to detect and give special
treatment to in a forthcoming patch for bug 1935269.

Differential Revision: https://phabricator.services.mozilla.com/D248526
This commit is contained in:
Daniel Holbert
2025-05-09 03:35:11 +00:00
committed by dholbert@mozilla.com
parent dda6b1197c
commit a1b0d56c0a
7 changed files with 96 additions and 0 deletions

View File

@@ -195,6 +195,17 @@ ClippedImage::GetHeight(int32_t* aHeight) {
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
ClippedImage::GetIntrinsicSize(ImageIntrinsicSize* aIntrinsicSize) {
if (!ShouldClip()) {
return InnerImage()->GetIntrinsicSize(aIntrinsicSize);
}
aIntrinsicSize->mWidth = Some(mClip.Width());
aIntrinsicSize->mHeight = Some(mClip.Height());
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
ClippedImage::GetIntrinsicSizeInAppUnits(nsSize* aSize) { ClippedImage::GetIntrinsicSizeInAppUnits(nsSize* aSize) {
if (!ShouldClip()) { if (!ShouldClip()) {

View File

@@ -35,6 +35,7 @@ class ClippedImage : public ImageWrapper {
NS_IMETHOD GetWidth(int32_t* aWidth) override; NS_IMETHOD GetWidth(int32_t* aWidth) override;
NS_IMETHOD GetHeight(int32_t* aHeight) override; NS_IMETHOD GetHeight(int32_t* aHeight) override;
NS_IMETHOD GetIntrinsicSize(ImageIntrinsicSize* aIntrinsicSize) override;
NS_IMETHOD GetIntrinsicSizeInAppUnits(nsSize* aSize) override; NS_IMETHOD GetIntrinsicSizeInAppUnits(nsSize* aSize) override;
AspectRatio GetIntrinsicRatio() override; AspectRatio GetIntrinsicRatio() override;
NS_IMETHOD_(already_AddRefed<SourceSurface>) NS_IMETHOD_(already_AddRefed<SourceSurface>)

View File

@@ -97,6 +97,15 @@ nsresult DynamicImage::GetNativeSizes(nsTArray<IntSize>&) {
size_t DynamicImage::GetNativeSizesLength() { return 0; } size_t DynamicImage::GetNativeSizesLength() { return 0; }
NS_IMETHODIMP
DynamicImage::GetIntrinsicSize(ImageIntrinsicSize* aIntrinsicSize) {
IntSize intSize(mDrawable->Size());
aIntrinsicSize->mWidth = Some(intSize.width);
aIntrinsicSize->mHeight = Some(intSize.height);
return NS_OK;
}
NS_IMETHODIMP NS_IMETHODIMP
DynamicImage::GetIntrinsicSizeInAppUnits(nsSize* aSize) { DynamicImage::GetIntrinsicSizeInAppUnits(nsSize* aSize) {
// XXXdholbert This probably needs to be scaled; see bug 1965106. // XXXdholbert This probably needs to be scaled; see bug 1965106.

View File

@@ -114,6 +114,11 @@ size_t ImageWrapper::GetNativeSizesLength() {
return mInnerImage->GetNativeSizesLength(); return mInnerImage->GetNativeSizesLength();
} }
NS_IMETHODIMP
ImageWrapper::GetIntrinsicSize(ImageIntrinsicSize* aIntrinsicSize) {
return mInnerImage->GetIntrinsicSize(aIntrinsicSize);
}
NS_IMETHODIMP NS_IMETHODIMP
ImageWrapper::GetIntrinsicSizeInAppUnits(nsSize* aSize) { ImageWrapper::GetIntrinsicSizeInAppUnits(nsSize* aSize) {
return mInnerImage->GetIntrinsicSizeInAppUnits(aSize); return mInnerImage->GetIntrinsicSizeInAppUnits(aSize);

View File

@@ -207,6 +207,20 @@ RasterImage::GetHeight(int32_t* aHeight) {
return NS_OK; return NS_OK;
} }
//******************************************************************************
NS_IMETHODIMP
RasterImage::GetIntrinsicSize(ImageIntrinsicSize* aIntrinsicSize) {
NS_ENSURE_ARG_POINTER(aIntrinsicSize);
if (mError) {
return NS_ERROR_FAILURE;
}
aIntrinsicSize->mWidth = Some(mSize.width);
aIntrinsicSize->mHeight = Some(mSize.height);
return NS_OK;
}
//****************************************************************************** //******************************************************************************
void RasterImage::MediaFeatureValuesChangedAllDocuments( void RasterImage::MediaFeatureValuesChangedAllDocuments(
const mozilla::MediaFeatureChange& aChange) {} const mozilla::MediaFeatureChange& aChange) {}

View File

@@ -447,6 +447,7 @@ static Maybe<int32_t> ClampedPxLengthOrNothing(
// imgIContainer methods // imgIContainer methods
//****************************************************************************** //******************************************************************************
NS_IMETHODIMP NS_IMETHODIMP
VectorImage::GetWidth(int32_t* aWidth) { VectorImage::GetWidth(int32_t* aWidth) {
if (mError || !mIsFullyLoaded) { if (mError || !mIsFullyLoaded) {
@@ -507,6 +508,25 @@ VectorImage::GetHeight(int32_t* aHeight) {
return NS_OK; return NS_OK;
} }
//******************************************************************************
NS_IMETHODIMP
VectorImage::GetIntrinsicSize(ImageIntrinsicSize* aIntrinsicSize) {
if (mError || !mIsFullyLoaded) {
return NS_ERROR_FAILURE;
}
SVGSVGElement* rootElem = mSVGDocumentWrapper->GetRootSVGElem();
if (MOZ_UNLIKELY(!rootElem)) {
return NS_ERROR_FAILURE;
}
aIntrinsicSize->mWidth =
ClampedPxLengthOrNothing(rootElem->GetIntrinsicWidth());
aIntrinsicSize->mHeight =
ClampedPxLengthOrNothing(rootElem->GetIntrinsicHeight());
return NS_OK;
}
//****************************************************************************** //******************************************************************************
NS_IMETHODIMP NS_IMETHODIMP
VectorImage::GetIntrinsicSizeInAppUnits(nsSize* aSize) { VectorImage::GetIntrinsicSizeInAppUnits(nsSize* aSize) {

View File

@@ -43,12 +43,34 @@ class ImageIntRegion;
class WebRenderImageProvider; class WebRenderImageProvider;
struct Orientation; struct Orientation;
struct Resolution; struct Resolution;
/**
* This represents an image's intrinsic size, in units of pixels (the same
* units as our 'width' and 'height' attributes). Both components are
* optional, because an image (particularly a vector image) may lack an
* intrinsic width and/or height.
*
* We use signed types for the components, but the values are expected to be
* nonnegative; any negative values should be considered an error. (Zero is
* valid, though.)
*
* Note that this is similar to a gfx::IntSize, except for the use of Maybe<>
* to reflect that the components are optional. This is also similar to
* nsIFrame.h's mozilla::IntrinsicSize class, with the difference being pixel
* units here vs. nscoord units there.
*/
struct ImageIntrinsicSize {
Maybe<int32_t> mWidth;
Maybe<int32_t> mHeight;
};
} }
} }
%} %}
native AspectRatio(mozilla::AspectRatio); native AspectRatio(mozilla::AspectRatio);
native ImageIntrinsicSize(mozilla::image::ImageIntrinsicSize);
native ImgDrawResult(mozilla::image::ImgDrawResult); native ImgDrawResult(mozilla::image::ImgDrawResult);
[ptr] native gfxContext(gfxContext); [ptr] native gfxContext(gfxContext);
[ref] native gfxMatrix(gfxMatrix); [ref] native gfxMatrix(gfxMatrix);
@@ -98,6 +120,20 @@ interface imgIContainer : nsISupports
*/ */
readonly attribute int32_t height; readonly attribute int32_t height;
/**
* The intrinsic size of this image in pixels. The values and units here are
* the same as those that the 'width' and 'height' attributes (declared
* above) would return.
*
* If an image lacks an intrinsic width and/or height, then that component
* will be Nothing() in the returned value. (This is different from the
* 'width' and 'height' attributes; they treat this case as an error, for
* historical reasons, but we can handle it more elegantly here.)
*
* In case of any error, an exception will be thrown.
*/
[noscript] readonly attribute ImageIntrinsicSize intrinsicSize;
/** /**
* The intrinsic size of this image in appunits. If the image has no intrinsic * The intrinsic size of this image in appunits. If the image has no intrinsic
* size in a dimension, -1 will be returned for that dimension. In the case of * size in a dimension, -1 will be returned for that dimension. In the case of