mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 1680387 - Apply intrinsic image resolution as appropriate in layout/style/dom, and update test expectations. r=tnikkel
This should be mostly straight-forward, since we have code for this anyways for image-set() and srcset. The only thing is that we were using floats for resolution, but since EXIF allows you to scale each axis separately, we now need to pass an image::Resolution instead. The main outstanding issue is the spec comment mentioned in the previous patch, about what happens if you have srcset/image-set and the image density specified together. For now I've implemented what the image-set() spec says, but this is subject to change before shipping of course. Differential Revision: https://phabricator.services.mozilla.com/D113265
This commit is contained in:
parent
6c4266f7f7
commit
1cdf344860
@ -288,7 +288,7 @@ bool PointerLockManager::SetPointerLock(Element* aElement, Document* aDocument,
|
||||
|
||||
// Hide the cursor and set pointer lock for future mouse events
|
||||
RefPtr<EventStateManager> esm = presContext->EventStateManager();
|
||||
esm->SetCursor(aCursorStyle, nullptr, 1.0f, Nothing(), widget, true);
|
||||
esm->SetCursor(aCursorStyle, nullptr, {}, Nothing(), widget, true);
|
||||
EventStateManager::SetPointerLock(widget, aElement);
|
||||
|
||||
return true;
|
||||
|
@ -7426,7 +7426,7 @@ void nsGlobalWindowOuter::SetCursorOuter(const nsACString& aCursor,
|
||||
|
||||
// Call esm and set cursor.
|
||||
aError = presContext->EventStateManager()->SetCursor(
|
||||
cursor, nullptr, 1.0f, Nothing(), widget, true);
|
||||
cursor, nullptr, {}, Nothing(), widget, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1216,32 +1216,6 @@ void nsImageLoadingContent::ForceImageState(bool aForce,
|
||||
mForcedImageState = EventStates(aState);
|
||||
}
|
||||
|
||||
uint32_t nsImageLoadingContent::NaturalWidth() {
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
if (mCurrentRequest) {
|
||||
mCurrentRequest->GetImage(getter_AddRefs(image));
|
||||
}
|
||||
|
||||
int32_t size = 0;
|
||||
if (image) {
|
||||
Unused << image->GetWidth(&size);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t nsImageLoadingContent::NaturalHeight() {
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
if (mCurrentRequest) {
|
||||
mCurrentRequest->GetImage(getter_AddRefs(image));
|
||||
}
|
||||
|
||||
int32_t size = 0;
|
||||
if (image) {
|
||||
Unused << image->GetHeight(&size);
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
CSSIntSize nsImageLoadingContent::GetWidthHeightForImage() {
|
||||
Element* element = AsContent()->AsElement();
|
||||
if (nsIFrame* frame = element->GetPrimaryFrame(FlushType::Layout)) {
|
||||
|
@ -232,9 +232,6 @@ class nsImageLoadingContent : public nsIImageLoadingContent {
|
||||
// want a non-const nsIContent.
|
||||
virtual nsIContent* AsContent() = 0;
|
||||
|
||||
// Hooks for subclasses to call to get the intrinsic width and height.
|
||||
uint32_t NaturalWidth();
|
||||
uint32_t NaturalHeight();
|
||||
/**
|
||||
* Get width and height of the current request, using given image request if
|
||||
* attributes are unset.
|
||||
|
@ -3906,7 +3906,7 @@ void EventStateManager::ClearFrameRefs(nsIFrame* aFrame) {
|
||||
struct CursorImage {
|
||||
gfx::IntPoint mHotspot;
|
||||
nsCOMPtr<imgIContainer> mContainer;
|
||||
float mResolution = 1.0f;
|
||||
ImageResolution mResolution;
|
||||
bool mEarlierCursorLoading = false;
|
||||
};
|
||||
|
||||
@ -3934,10 +3934,7 @@ static bool ShouldBlockCustomCursor(nsPresContext* aPresContext,
|
||||
int32_t height = 0;
|
||||
aCursor.mContainer->GetWidth(&width);
|
||||
aCursor.mContainer->GetHeight(&height);
|
||||
if (aCursor.mResolution != 0.0f && aCursor.mResolution != 1.0f) {
|
||||
width = std::round(width / aCursor.mResolution);
|
||||
height = std::round(height / aCursor.mResolution);
|
||||
}
|
||||
aCursor.mResolution.ApplyTo(width, height);
|
||||
|
||||
int32_t maxSize = StaticPrefs::layout_cursor_block_max_size();
|
||||
|
||||
@ -4010,8 +4007,7 @@ static CursorImage ComputeCustomCursor(nsPresContext* aPresContext,
|
||||
MOZ_ASSERT(image.image.IsImageRequestType(),
|
||||
"Cursor image should only parse url() types");
|
||||
uint32_t status;
|
||||
auto [finalImage, resolution] = image.image.FinalImageAndResolution();
|
||||
imgRequestProxy* req = finalImage->GetImageRequest();
|
||||
imgRequestProxy* req = image.image.GetImageRequest();
|
||||
if (!req || NS_FAILED(req->GetImageStatus(&status))) {
|
||||
continue;
|
||||
}
|
||||
@ -4033,14 +4029,15 @@ static CursorImage ComputeCustomCursor(nsPresContext* aPresContext,
|
||||
image.has_hotspot ? Some(gfx::Point{image.hotspot_x, image.hotspot_y})
|
||||
: Nothing();
|
||||
gfx::IntPoint hotspot = ComputeHotspot(container, specifiedHotspot);
|
||||
CursorImage result{hotspot, std::move(container), resolution, loading};
|
||||
CursorImage result{hotspot, std::move(container),
|
||||
image.image.GetResolution(), loading};
|
||||
if (ShouldBlockCustomCursor(aPresContext, aEvent, result)) {
|
||||
continue;
|
||||
}
|
||||
// This is the one we want!
|
||||
return result;
|
||||
}
|
||||
return {{}, nullptr, 1.0f, loading};
|
||||
return {{}, nullptr, {}, loading};
|
||||
}
|
||||
|
||||
void EventStateManager::UpdateCursor(nsPresContext* aPresContext,
|
||||
@ -4053,7 +4050,7 @@ void EventStateManager::UpdateCursor(nsPresContext* aPresContext,
|
||||
|
||||
auto cursor = StyleCursorKind::Default;
|
||||
nsCOMPtr<imgIContainer> container;
|
||||
float resolution = 1.0f;
|
||||
ImageResolution resolution;
|
||||
Maybe<gfx::IntPoint> hotspot;
|
||||
|
||||
// If cursor is locked just use the locked one
|
||||
@ -4138,7 +4135,7 @@ void EventStateManager::ClearCachedWidgetCursor(nsIFrame* aTargetFrame) {
|
||||
|
||||
nsresult EventStateManager::SetCursor(StyleCursorKind aCursor,
|
||||
imgIContainer* aContainer,
|
||||
float aResolution,
|
||||
const ImageResolution& aResolution,
|
||||
const Maybe<gfx::IntPoint>& aHotspot,
|
||||
nsIWidget* aWidget, bool aLockCursor) {
|
||||
EnsureDocument(mPresContext);
|
||||
|
@ -243,9 +243,9 @@ class EventStateManager : public nsSupportsWeakReference, public nsIObserver {
|
||||
bool CheckIfEventMatchesAccessKey(WidgetKeyboardEvent* aEvent,
|
||||
nsPresContext* aPresContext);
|
||||
|
||||
nsresult SetCursor(StyleCursorKind aCursor, imgIContainer* aContainer,
|
||||
float aResolution, const Maybe<gfx::IntPoint>& aHotspot,
|
||||
nsIWidget* aWidget, bool aLockCursor);
|
||||
nsresult SetCursor(StyleCursorKind, imgIContainer*, const ImageResolution&,
|
||||
const Maybe<gfx::IntPoint>& aHotspot, nsIWidget* aWidget,
|
||||
bool aLockCursor);
|
||||
|
||||
/**
|
||||
* Checks if the current mouse over element matches the given
|
||||
|
@ -710,28 +710,33 @@ uint32_t HTMLImageElement::Height() { return GetWidthHeightForImage().height; }
|
||||
|
||||
uint32_t HTMLImageElement::Width() { return GetWidthHeightForImage().width; }
|
||||
|
||||
uint32_t HTMLImageElement::NaturalHeight() {
|
||||
uint32_t height = nsImageLoadingContent::NaturalHeight();
|
||||
|
||||
if (mResponsiveSelector) {
|
||||
double density = mResponsiveSelector->GetSelectedImageDensity();
|
||||
MOZ_ASSERT(density >= 0.0);
|
||||
height = NSToIntRound(double(height) / density);
|
||||
nsIntSize HTMLImageElement::NaturalSize() {
|
||||
if (!mCurrentRequest) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
uint32_t HTMLImageElement::NaturalWidth() {
|
||||
uint32_t width = nsImageLoadingContent::NaturalWidth();
|
||||
|
||||
if (mResponsiveSelector) {
|
||||
double density = mResponsiveSelector->GetSelectedImageDensity();
|
||||
MOZ_ASSERT(density >= 0.0);
|
||||
width = NSToIntRound(double(width) / density);
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
mCurrentRequest->GetImage(getter_AddRefs(image));
|
||||
if (!image) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return width;
|
||||
nsIntSize size;
|
||||
Unused << image->GetHeight(&size.height);
|
||||
Unused << image->GetWidth(&size.width);
|
||||
|
||||
ImageResolution resolution = image->GetResolution();
|
||||
// NOTE(emilio): What we implement here matches the image-set() spec, but it's
|
||||
// unclear whether this is the right thing to do, see
|
||||
// https://github.com/whatwg/html/pull/5574#issuecomment-826335244.
|
||||
if (mResponsiveSelector) {
|
||||
float density = mResponsiveSelector->GetSelectedImageDensity();
|
||||
MOZ_ASSERT(density >= 0.0);
|
||||
resolution = {density, density};
|
||||
}
|
||||
|
||||
resolution.ApplyTo(size.width, size.height);
|
||||
return size;
|
||||
}
|
||||
|
||||
nsresult HTMLImageElement::CopyInnerTo(HTMLImageElement* aDest) {
|
||||
|
@ -97,8 +97,11 @@ class HTMLImageElement final : public nsGenericHTMLElement,
|
||||
void SetHeight(uint32_t aHeight, ErrorResult& aError) {
|
||||
SetUnsignedIntAttr(nsGkAtoms::height, aHeight, 0, aError);
|
||||
}
|
||||
uint32_t NaturalWidth();
|
||||
uint32_t NaturalHeight();
|
||||
|
||||
nsIntSize NaturalSize();
|
||||
uint32_t NaturalHeight() { return NaturalSize().height; }
|
||||
uint32_t NaturalWidth() { return NaturalSize().width; }
|
||||
|
||||
bool Complete();
|
||||
uint32_t Hspace() {
|
||||
return GetDimensionAttrAsUnsignedInt(nsGkAtoms::hspace, 0);
|
||||
|
@ -2183,7 +2183,8 @@ mozilla::ipc::IPCResult BrowserParent::RecvAsyncMessage(
|
||||
mozilla::ipc::IPCResult BrowserParent::RecvSetCursor(
|
||||
const nsCursor& aCursor, const bool& aHasCustomCursor,
|
||||
const nsCString& aCursorData, const uint32_t& aWidth,
|
||||
const uint32_t& aHeight, const float& aResolution, const uint32_t& aStride,
|
||||
const uint32_t& aHeight, const float& aResolutionX,
|
||||
const float& aResolutionY, const uint32_t& aStride,
|
||||
const gfx::SurfaceFormat& aFormat, const uint32_t& aHotspotX,
|
||||
const uint32_t& aHotspotY, const bool& aForce) {
|
||||
nsCOMPtr<nsIWidget> widget = GetWidget();
|
||||
@ -2212,8 +2213,11 @@ mozilla::ipc::IPCResult BrowserParent::RecvSetCursor(
|
||||
cursorImage = image::ImageOps::CreateFromDrawable(drawable);
|
||||
}
|
||||
|
||||
mCursor = nsIWidget::Cursor{aCursor, std::move(cursorImage), aHotspotX,
|
||||
aHotspotY, aResolution};
|
||||
mCursor = nsIWidget::Cursor{aCursor,
|
||||
std::move(cursorImage),
|
||||
aHotspotX,
|
||||
aHotspotY,
|
||||
{aResolutionX, aResolutionY}};
|
||||
if (!mRemoteTargetSetsCursor) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
@ -386,9 +386,10 @@ class BrowserParent final : public PBrowserParent,
|
||||
mozilla::ipc::IPCResult RecvSetCursor(
|
||||
const nsCursor& aValue, const bool& aHasCustomCursor,
|
||||
const nsCString& aCursorData, const uint32_t& aWidth,
|
||||
const uint32_t& aHeight, const float& aResolution,
|
||||
const uint32_t& aStride, const gfx::SurfaceFormat& aFormat,
|
||||
const uint32_t& aHotspotX, const uint32_t& aHotspotY, const bool& aForce);
|
||||
const uint32_t& aHeight, const float& aResolutionX,
|
||||
const float& aResolutionY, const uint32_t& aStride,
|
||||
const gfx::SurfaceFormat& aFormat, const uint32_t& aHotspotX,
|
||||
const uint32_t& aHotspotY, const bool& aForce);
|
||||
|
||||
mozilla::ipc::IPCResult RecvSetLinkStatus(const nsString& aStatus);
|
||||
|
||||
|
@ -389,8 +389,10 @@ parent:
|
||||
* Width of the image.
|
||||
* @param height
|
||||
* Height of the image.
|
||||
* @param resolution
|
||||
* Resolution of the image in dppx units.
|
||||
* @param resolutionX
|
||||
* Resolution of the image X axis in dppx units.
|
||||
* @param resolutionY
|
||||
* Resolution of the image Y axis in dppx units.
|
||||
* @param stride
|
||||
* Stride used in the image data.
|
||||
* @param format
|
||||
@ -407,7 +409,8 @@ parent:
|
||||
bool hasCustomCursor,
|
||||
nsCString customCursorData,
|
||||
uint32_t width, uint32_t height,
|
||||
float resolution, uint32_t stride, SurfaceFormat format,
|
||||
float resolutionX, float resolutionY,
|
||||
uint32_t stride, SurfaceFormat format,
|
||||
uint32_t hotspotX, uint32_t hotspotY, bool force);
|
||||
|
||||
/**
|
||||
|
@ -63,6 +63,15 @@ struct Resolution {
|
||||
ApplyXTo(aWidth);
|
||||
ApplyYTo(aHeight);
|
||||
}
|
||||
|
||||
void ApplyInverseTo(int32_t& aWidth, int32_t& aHeight) {
|
||||
if (mX != 1.0f) {
|
||||
aWidth = std::round(float(aWidth) * mX);
|
||||
}
|
||||
if (mY != 1.0f) {
|
||||
aHeight = std::round(float(aHeight) * mY);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
|
@ -6294,6 +6294,8 @@ ImgDrawResult nsLayoutUtils::DrawSingleUnscaledImage(
|
||||
CSSIntSize imageSize;
|
||||
aImage->GetWidth(&imageSize.width);
|
||||
aImage->GetHeight(&imageSize.height);
|
||||
aImage->GetResolution().ApplyTo(imageSize.width, imageSize.height);
|
||||
|
||||
if (imageSize.width < 1 || imageSize.height < 1) {
|
||||
NS_WARNING("Image width or height is non-positive");
|
||||
return ImgDrawResult::TEMPORARY_ERROR;
|
||||
@ -6321,13 +6323,15 @@ ImgDrawResult nsLayoutUtils::DrawSingleUnscaledImage(
|
||||
/* static */
|
||||
ImgDrawResult nsLayoutUtils::DrawSingleImage(
|
||||
gfxContext& aContext, nsPresContext* aPresContext, imgIContainer* aImage,
|
||||
float aResolution, SamplingFilter aSamplingFilter, const nsRect& aDest,
|
||||
const nsRect& aDirty, const Maybe<SVGImageContext>& aSVGContext,
|
||||
uint32_t aImageFlags, const nsPoint* aAnchorPoint,
|
||||
const nsRect* aSourceArea) {
|
||||
SamplingFilter aSamplingFilter, const nsRect& aDest, const nsRect& aDirty,
|
||||
const Maybe<SVGImageContext>& aSVGContext, uint32_t aImageFlags,
|
||||
const nsPoint* aAnchorPoint, const nsRect* aSourceArea) {
|
||||
nscoord appUnitsPerCSSPixel = AppUnitsPerCSSPixel();
|
||||
CSSIntSize pixelImageSize(
|
||||
ComputeSizeForDrawingWithFallback(aImage, aResolution, aDest.Size()));
|
||||
// NOTE(emilio): We can hardcode resolution to 1 here, since we're interested
|
||||
// in the actual image pixels, for snapping purposes, not on the adjusted
|
||||
// size.
|
||||
CSSIntSize pixelImageSize(ComputeSizeForDrawingWithFallback(
|
||||
aImage, ImageResolution(), aDest.Size()));
|
||||
if (pixelImageSize.width < 1 || pixelImageSize.height < 1) {
|
||||
NS_ASSERTION(pixelImageSize.width >= 0 && pixelImageSize.height >= 0,
|
||||
"Image width or height is negative");
|
||||
@ -6368,7 +6372,7 @@ ImgDrawResult nsLayoutUtils::DrawSingleImage(
|
||||
|
||||
/* static */
|
||||
void nsLayoutUtils::ComputeSizeForDrawing(
|
||||
imgIContainer* aImage, float aResolution,
|
||||
imgIContainer* aImage, const ImageResolution& aResolution,
|
||||
/* outparam */ CSSIntSize& aImageSize,
|
||||
/* outparam */ AspectRatio& aIntrinsicRatio,
|
||||
/* outparam */ bool& aGotWidth,
|
||||
@ -6378,13 +6382,11 @@ void nsLayoutUtils::ComputeSizeForDrawing(
|
||||
Maybe<AspectRatio> intrinsicRatio = aImage->GetIntrinsicRatio();
|
||||
aIntrinsicRatio = intrinsicRatio.valueOr(AspectRatio());
|
||||
|
||||
if (aResolution != 0.0f && aResolution != 1.0f) {
|
||||
if (aGotWidth) {
|
||||
aImageSize.width = std::round(float(aImageSize.width) / aResolution);
|
||||
}
|
||||
if (aGotHeight) {
|
||||
aImageSize.height = std::round(float(aImageSize.height) / aResolution);
|
||||
}
|
||||
if (aGotWidth) {
|
||||
aResolution.ApplyXTo(aImageSize.width);
|
||||
}
|
||||
if (aGotHeight) {
|
||||
aResolution.ApplyYTo(aImageSize.height);
|
||||
}
|
||||
|
||||
if (!(aGotWidth && aGotHeight) && intrinsicRatio.isNothing()) {
|
||||
@ -6397,7 +6399,8 @@ void nsLayoutUtils::ComputeSizeForDrawing(
|
||||
|
||||
/* static */
|
||||
CSSIntSize nsLayoutUtils::ComputeSizeForDrawingWithFallback(
|
||||
imgIContainer* aImage, float aResolution, const nsSize& aFallbackSize) {
|
||||
imgIContainer* aImage, const ImageResolution& aResolution,
|
||||
const nsSize& aFallbackSize) {
|
||||
CSSIntSize imageSize;
|
||||
AspectRatio imageRatio;
|
||||
bool gotHeight, gotWidth;
|
||||
|
@ -103,6 +103,9 @@ namespace gfx {
|
||||
struct RectCornerRadii;
|
||||
enum class ShapedTextFlags : uint16_t;
|
||||
} // namespace gfx
|
||||
namespace image {
|
||||
struct Resolution;
|
||||
}
|
||||
namespace layers {
|
||||
struct FrameMetrics;
|
||||
struct ScrollMetadata;
|
||||
@ -1901,11 +1904,6 @@ class nsLayoutUtils {
|
||||
* appropriate scale and transform for drawing in
|
||||
* app units.
|
||||
* @param aImage The image.
|
||||
* @param aResolution The resolution specified by the author for the
|
||||
* image, in dppx. This will affect the intrinsic
|
||||
* size of the image (so e.g., if resolution is 2,
|
||||
* and the image is 100x100, the intrinsic size of
|
||||
* the image will be 50x50).
|
||||
* @param aDest The area that the image should fill.
|
||||
* @param aDirty Pixels outside this area may be skipped.
|
||||
* @param aSVGContext Optionally provides an SVGImageContext.
|
||||
@ -1927,9 +1925,9 @@ class nsLayoutUtils {
|
||||
*/
|
||||
static ImgDrawResult DrawSingleImage(
|
||||
gfxContext& aContext, nsPresContext* aPresContext, imgIContainer* aImage,
|
||||
float aResolution, SamplingFilter aSamplingFilter, const nsRect& aDest,
|
||||
const nsRect& aDirty, const mozilla::Maybe<SVGImageContext>& aSVGContext,
|
||||
uint32_t aImageFlags, const nsPoint* aAnchorPoint = nullptr,
|
||||
SamplingFilter aSamplingFilter, const nsRect& aDest, const nsRect& aDirty,
|
||||
const mozilla::Maybe<SVGImageContext>& aSVGContext, uint32_t aImageFlags,
|
||||
const nsPoint* aAnchorPoint = nullptr,
|
||||
const nsRect* aSourceArea = nullptr);
|
||||
|
||||
/**
|
||||
@ -1947,8 +1945,16 @@ class nsLayoutUtils {
|
||||
* NOTE: This method is similar to ComputeSizeWithIntrinsicDimensions. The
|
||||
* difference is that this one is simpler and is suited to places where we
|
||||
* have less information about the frame tree.
|
||||
*
|
||||
* @param aResolution The resolution specified by the author for the image, or
|
||||
* its intrinsic resolution.
|
||||
*
|
||||
* This will affect the intrinsic size size of the image
|
||||
* (so e.g., if resolution is 2, and the image is 100x100,
|
||||
* the intrinsic size of the image will be 50x50).
|
||||
*/
|
||||
static void ComputeSizeForDrawing(imgIContainer* aImage, float aResolution,
|
||||
static void ComputeSizeForDrawing(imgIContainer* aImage,
|
||||
const mozilla::image::Resolution&,
|
||||
CSSIntSize& aImageSize,
|
||||
AspectRatio& aIntrinsicRatio,
|
||||
bool& aGotWidth, bool& aGotHeight);
|
||||
@ -1962,7 +1968,8 @@ class nsLayoutUtils {
|
||||
* dimensions, the corresponding dimension of aFallbackSize is used instead.
|
||||
*/
|
||||
static CSSIntSize ComputeSizeForDrawingWithFallback(
|
||||
imgIContainer* aImage, float aResolution, const nsSize& aFallbackSize);
|
||||
imgIContainer* aImage, const mozilla::image::Resolution&,
|
||||
const nsSize& aFallbackSize);
|
||||
|
||||
/**
|
||||
* Given the image container, frame, and dest rect, determine the best fitting
|
||||
|
@ -356,6 +356,38 @@ static bool SizeIsAvailable(imgIRequest* aRequest) {
|
||||
return NS_SUCCEEDED(rv) && (imageStatus & imgIRequest::STATUS_SIZE_AVAILABLE);
|
||||
}
|
||||
|
||||
const StyleImage* nsImageFrame::GetImageFromStyle() const {
|
||||
if (mKind == Kind::ImageElement) {
|
||||
return nullptr;
|
||||
}
|
||||
uint32_t contentIndex = 0;
|
||||
const nsStyleContent* styleContent = StyleContent();
|
||||
if (mKind == Kind::ContentPropertyAtIndex) {
|
||||
MOZ_RELEASE_ASSERT(
|
||||
mContent->IsHTMLElement(nsGkAtoms::mozgeneratedcontentimage));
|
||||
contentIndex = static_cast<GeneratedImageContent*>(mContent.get())->Index();
|
||||
|
||||
// TODO(emilio): Consider inheriting the `content` property instead of doing
|
||||
// this parent traversal?
|
||||
nsIFrame* parent = GetParent();
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
parent->GetContent()->IsGeneratedContentContainerForMarker() ||
|
||||
parent->GetContent()->IsGeneratedContentContainerForAfter() ||
|
||||
parent->GetContent()->IsGeneratedContentContainerForBefore());
|
||||
nsIFrame* nonAnonymousParent = parent;
|
||||
while (nonAnonymousParent->Style()->IsAnonBox()) {
|
||||
nonAnonymousParent = nonAnonymousParent->GetParent();
|
||||
}
|
||||
MOZ_DIAGNOSTIC_ASSERT(parent->GetContent() ==
|
||||
nonAnonymousParent->GetContent());
|
||||
styleContent = nonAnonymousParent->StyleContent();
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(contentIndex < styleContent->ContentCount());
|
||||
auto& contentItem = styleContent->ContentAt(contentIndex);
|
||||
MOZ_RELEASE_ASSERT(contentItem.IsImage());
|
||||
return &contentItem.AsImage();
|
||||
}
|
||||
|
||||
void nsImageFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
nsIFrame* aPrevInFlow) {
|
||||
MOZ_ASSERT_IF(aPrevInFlow,
|
||||
@ -378,33 +410,11 @@ void nsImageFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||
// that it can register images.
|
||||
imageLoader->FrameCreated(this);
|
||||
} else {
|
||||
uint32_t contentIndex = 0;
|
||||
const nsStyleContent* styleContent = StyleContent();
|
||||
if (mKind == Kind::ContentPropertyAtIndex) {
|
||||
MOZ_RELEASE_ASSERT(
|
||||
aParent->GetContent()->IsGeneratedContentContainerForMarker() ||
|
||||
aParent->GetContent()->IsGeneratedContentContainerForAfter() ||
|
||||
aParent->GetContent()->IsGeneratedContentContainerForBefore());
|
||||
MOZ_RELEASE_ASSERT(
|
||||
aContent->IsHTMLElement(nsGkAtoms::mozgeneratedcontentimage));
|
||||
nsIFrame* nonAnonymousParent = aParent;
|
||||
while (nonAnonymousParent->Style()->IsAnonBox()) {
|
||||
nonAnonymousParent = nonAnonymousParent->GetParent();
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(aParent->GetContent() ==
|
||||
nonAnonymousParent->GetContent());
|
||||
styleContent = nonAnonymousParent->StyleContent();
|
||||
contentIndex = static_cast<GeneratedImageContent*>(aContent)->Index();
|
||||
}
|
||||
MOZ_RELEASE_ASSERT(contentIndex < styleContent->ContentCount());
|
||||
MOZ_RELEASE_ASSERT(styleContent->ContentAt(contentIndex).IsImage());
|
||||
const StyleImage& image = styleContent->ContentAt(contentIndex).AsImage();
|
||||
MOZ_ASSERT(image.IsImageRequestType(),
|
||||
const StyleImage* image = GetImageFromStyle();
|
||||
MOZ_ASSERT(image->IsImageRequestType(),
|
||||
"Content image should only parse url() type");
|
||||
auto [finalImage, resolution] = image.FinalImageAndResolution();
|
||||
Document* doc = PresContext()->Document();
|
||||
if (imgRequestProxy* proxy = finalImage->GetImageRequest()) {
|
||||
mContentURLRequestResolution = resolution;
|
||||
if (imgRequestProxy* proxy = image->GetImageRequest()) {
|
||||
proxy->Clone(mListener, doc, getter_AddRefs(mContentURLRequest));
|
||||
SetupForContentURLRequest();
|
||||
}
|
||||
@ -457,34 +467,27 @@ void nsImageFrame::SetupForContentURLRequest() {
|
||||
}
|
||||
|
||||
static void ScaleIntrinsicSizeForDensity(IntrinsicSize& aSize,
|
||||
double aDensity) {
|
||||
if (aDensity == 1.0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ImageResolution& aResolution) {
|
||||
if (aSize.width) {
|
||||
aSize.width = Some(NSToCoordRound(double(*aSize.width) / aDensity));
|
||||
aResolution.ApplyXTo(aSize.width.ref());
|
||||
}
|
||||
if (aSize.height) {
|
||||
aSize.height = Some(NSToCoordRound(double(*aSize.height) / aDensity));
|
||||
aResolution.ApplyYTo(aSize.height.ref());
|
||||
}
|
||||
}
|
||||
|
||||
static void ScaleIntrinsicSizeForDensity(nsIContent& aContent,
|
||||
static void ScaleIntrinsicSizeForDensity(imgIContainer* aImage,
|
||||
nsIContent& aContent,
|
||||
IntrinsicSize& aSize) {
|
||||
auto* image = HTMLImageElement::FromNode(aContent);
|
||||
if (!image) {
|
||||
return;
|
||||
if (auto* image = HTMLImageElement::FromNode(aContent)) {
|
||||
if (auto* selector = image->GetResponsiveImageSelector()) {
|
||||
float density = selector->GetSelectedImageDensity();
|
||||
MOZ_ASSERT(density >= 0.0);
|
||||
ScaleIntrinsicSizeForDensity(aSize, ImageResolution{density, density});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ResponsiveImageSelector* selector = image->GetResponsiveImageSelector();
|
||||
if (!selector) {
|
||||
return;
|
||||
}
|
||||
|
||||
double density = selector->GetSelectedImageDensity();
|
||||
MOZ_ASSERT(density >= 0.0);
|
||||
ScaleIntrinsicSizeForDensity(aSize, density);
|
||||
ScaleIntrinsicSizeForDensity(aSize, aImage->GetResolution());
|
||||
}
|
||||
|
||||
static IntrinsicSize ComputeIntrinsicSize(imgIContainer* aImage,
|
||||
@ -502,10 +505,10 @@ static IntrinsicSize ComputeIntrinsicSize(imgIContainer* aImage,
|
||||
intrinsicSize.width = size.width == -1 ? Nothing() : Some(size.width);
|
||||
intrinsicSize.height = size.height == -1 ? Nothing() : Some(size.height);
|
||||
if (aKind == nsImageFrame::Kind::ImageElement) {
|
||||
ScaleIntrinsicSizeForDensity(*aFrame.GetContent(), intrinsicSize);
|
||||
ScaleIntrinsicSizeForDensity(aImage, *aFrame.GetContent(), intrinsicSize);
|
||||
} else {
|
||||
ScaleIntrinsicSizeForDensity(intrinsicSize,
|
||||
aFrame.GetContentURLRequestResolution());
|
||||
aFrame.GetImageFromStyle()->GetResolution());
|
||||
}
|
||||
return intrinsicSize;
|
||||
}
|
||||
@ -1486,7 +1489,7 @@ ImgDrawResult nsImageFrame::DisplayAltFeedback(gfxContext& aRenderingContext,
|
||||
nsRect dest(flushRight ? inner.XMost() - size : inner.x, inner.y, size,
|
||||
size);
|
||||
result = nsLayoutUtils::DrawSingleImage(
|
||||
aRenderingContext, PresContext(), imgCon, /* aResolution = */ 1.0f,
|
||||
aRenderingContext, PresContext(), imgCon,
|
||||
nsLayoutUtils::GetSamplingFilterForFrame(this), dest, aDirtyRect,
|
||||
/* no SVGImageContext */ Nothing(), aFlags);
|
||||
}
|
||||
@ -2090,10 +2093,8 @@ ImgDrawResult nsImageFrame::PaintImage(gfxContext& aRenderingContext,
|
||||
Maybe<SVGImageContext> svgContext;
|
||||
SVGImageContext::MaybeStoreContextPaint(svgContext, this, aImage);
|
||||
|
||||
// We've already accounted for resolution via mIntrinsicSize, which influences
|
||||
// the dest rect, so we don't need to worry about it here..
|
||||
ImgDrawResult result = nsLayoutUtils::DrawSingleImage(
|
||||
aRenderingContext, PresContext(), aImage, /* aResolution = */ 1.0f,
|
||||
aRenderingContext, PresContext(), aImage,
|
||||
nsLayoutUtils::GetSamplingFilterForFrame(this), dest, aDirtyRect,
|
||||
svgContext, flags, &anchorPoint);
|
||||
|
||||
|
@ -103,11 +103,7 @@ class nsImageFrame : public nsAtomicContainerFrame, public nsIReflowCallback {
|
||||
void SetupForContentURLRequest();
|
||||
bool ShouldShowBrokenImageIcon() const;
|
||||
|
||||
// Get the resolution, in dppx, for the image that mContentURLRequest
|
||||
// represents.
|
||||
float GetContentURLRequestResolution() const {
|
||||
return mContentURLRequestResolution;
|
||||
}
|
||||
const mozilla::StyleImage* GetImageFromStyle() const;
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
mozilla::a11y::AccType AccessibleType() override;
|
||||
@ -359,7 +355,6 @@ class nsImageFrame : public nsAtomicContainerFrame, public nsIReflowCallback {
|
||||
|
||||
// An image request created for content: url(..).
|
||||
RefPtr<imgRequestProxy> mContentURLRequest;
|
||||
float mContentURLRequestResolution = 1.0f;
|
||||
|
||||
nsCOMPtr<imgIContainer> mImage;
|
||||
nsCOMPtr<imgIContainer> mPrevImage;
|
||||
|
@ -50,6 +50,9 @@ nsSize CSSSizeOrRatio::ComputeConcreteSize() const {
|
||||
nsImageRenderer::nsImageRenderer(nsIFrame* aForFrame, const StyleImage* aImage,
|
||||
uint32_t aFlags)
|
||||
: mForFrame(aForFrame),
|
||||
mImage(&aImage->FinalImage()),
|
||||
mImageResolution(aImage->GetResolution()),
|
||||
mType(mImage->tag),
|
||||
mImageContainer(nullptr),
|
||||
mGradientData(nullptr),
|
||||
mPaintServerFrame(nullptr),
|
||||
@ -57,12 +60,7 @@ nsImageRenderer::nsImageRenderer(nsIFrame* aForFrame, const StyleImage* aImage,
|
||||
mSize(0, 0),
|
||||
mFlags(aFlags),
|
||||
mExtendMode(ExtendMode::CLAMP),
|
||||
mMaskOp(StyleMaskMode::MatchSource) {
|
||||
auto pair = aImage->FinalImageAndResolution();
|
||||
mImage = pair.first;
|
||||
mType = mImage->tag;
|
||||
mImageResolution = pair.second;
|
||||
}
|
||||
mMaskOp(StyleMaskMode::MatchSource) {}
|
||||
|
||||
bool nsImageRenderer::PrepareImage() {
|
||||
if (mImage->IsNone()) {
|
||||
@ -940,9 +938,8 @@ ImgDrawResult nsImageRenderer::DrawBorderImageComponent(
|
||||
|
||||
if (!RequiresScaling(aFill, aHFill, aVFill, aUnitSize)) {
|
||||
ImgDrawResult result = nsLayoutUtils::DrawSingleImage(
|
||||
aRenderingContext, aPresContext, subImage, mImageResolution,
|
||||
samplingFilter, aFill, aDirtyRect,
|
||||
/* no SVGImageContext */ Nothing(), drawFlags);
|
||||
aRenderingContext, aPresContext, subImage, samplingFilter, aFill,
|
||||
aDirtyRect, /* no SVGImageContext */ Nothing(), drawFlags);
|
||||
|
||||
if (!mImage->IsComplete()) {
|
||||
result &= ImgDrawResult::SUCCESS_NOT_COMPLETE;
|
||||
@ -1010,9 +1007,8 @@ ImgDrawResult nsImageRenderer::DrawShapeImage(nsPresContext* aPresContext,
|
||||
// rendered pixel has an alpha that precisely matches the alpha of the
|
||||
// closest pixel in the image.
|
||||
return nsLayoutUtils::DrawSingleImage(
|
||||
aRenderingContext, aPresContext, mImageContainer, mImageResolution,
|
||||
SamplingFilter::POINT, dest, dest, Nothing(), drawFlags, nullptr,
|
||||
nullptr);
|
||||
aRenderingContext, aPresContext, mImageContainer, SamplingFilter::POINT,
|
||||
dest, dest, Nothing(), drawFlags);
|
||||
}
|
||||
|
||||
if (mImage->IsGradient()) {
|
||||
|
@ -299,7 +299,7 @@ class nsImageRenderer {
|
||||
|
||||
nsIFrame* mForFrame;
|
||||
const mozilla::StyleImage* mImage;
|
||||
float mImageResolution;
|
||||
ImageResolution mImageResolution;
|
||||
mozilla::StyleImage::Tag mType;
|
||||
nsCOMPtr<imgIContainer> mImageContainer;
|
||||
const mozilla::StyleGradient* mGradientData;
|
||||
|
@ -30,6 +30,7 @@
|
||||
# include "nsCSSPropertyID.h"
|
||||
# include "nsCompatibility.h"
|
||||
# include "nsIURI.h"
|
||||
# include "mozilla/image/Resolution.h"
|
||||
# include <atomic>
|
||||
|
||||
struct RawServoAnimationValueTable;
|
||||
|
@ -942,20 +942,16 @@ inline bool RestyleHint::DefinitelyRecascadesAllSubtree() const {
|
||||
}
|
||||
|
||||
template <>
|
||||
inline std::pair<const StyleImage*, float> StyleImage::FinalImageAndResolution()
|
||||
const {
|
||||
if (!IsImageSet()) {
|
||||
return {this, 1.0f};
|
||||
}
|
||||
auto& set = AsImageSet();
|
||||
auto& selectedItem = set->items.AsSpan()[set->selected_index];
|
||||
return {selectedItem.image.FinalImageAndResolution().first,
|
||||
selectedItem.resolution._0};
|
||||
}
|
||||
ImageResolution StyleImage::GetResolution() const;
|
||||
|
||||
template <>
|
||||
inline const StyleImage& StyleImage::FinalImage() const {
|
||||
return *FinalImageAndResolution().first;
|
||||
if (!IsImageSet()) {
|
||||
return *this;
|
||||
}
|
||||
auto& set = AsImageSet();
|
||||
auto& selectedItem = set->items.AsSpan()[set->selected_index];
|
||||
return selectedItem.image.FinalImage();
|
||||
}
|
||||
|
||||
template <>
|
||||
|
@ -1629,10 +1629,27 @@ void StyleImage::ResolveImage(Document& aDoc, const StyleImage* aOld) {
|
||||
const_cast<StyleComputedImageUrl*>(url)->ResolveImage(aDoc, old);
|
||||
}
|
||||
|
||||
template <>
|
||||
ImageResolution StyleImage::GetResolution() const {
|
||||
if (IsImageSet()) {
|
||||
auto& set = AsImageSet();
|
||||
float r = set->items.AsSpan()[set->selected_index].resolution._0;
|
||||
if (MOZ_LIKELY(r != 0.0f)) {
|
||||
return ImageResolution(r, r);
|
||||
}
|
||||
} else if (imgRequestProxy* request = GetImageRequest()) {
|
||||
RefPtr<imgIContainer> image;
|
||||
request->GetImage(getter_AddRefs(image));
|
||||
if (image) {
|
||||
return image->GetResolution();
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template <>
|
||||
Maybe<CSSIntSize> StyleImage::GetIntrinsicSize() const {
|
||||
auto [finalImage, resolution] = FinalImageAndResolution();
|
||||
imgRequestProxy* request = finalImage->GetImageRequest();
|
||||
imgRequestProxy* request = GetImageRequest();
|
||||
if (!request) {
|
||||
return Nothing();
|
||||
}
|
||||
@ -1647,10 +1664,7 @@ Maybe<CSSIntSize> StyleImage::GetIntrinsicSize() const {
|
||||
int32_t w = 0, h = 0;
|
||||
image->GetWidth(&w);
|
||||
image->GetHeight(&h);
|
||||
if (resolution != 0.0f && resolution != 1.0f) {
|
||||
w = std::round(float(w) / resolution);
|
||||
h = std::round(float(h) / resolution);
|
||||
}
|
||||
GetResolution().ApplyTo(w, h);
|
||||
return Some(CSSIntSize{w, h});
|
||||
}
|
||||
|
||||
@ -1909,9 +1923,9 @@ static bool SizeDependsOnPositioningAreaSize(const StyleBackgroundSize& aSize,
|
||||
bool hasWidth, hasHeight;
|
||||
// We could bother getting the right resolution here but it doesn't matter
|
||||
// since we ignore `imageSize`.
|
||||
nsLayoutUtils::ComputeSizeForDrawing(imgContainer,
|
||||
/* aResolution = */ 1.0f, imageSize,
|
||||
imageRatio, hasWidth, hasHeight);
|
||||
nsLayoutUtils::ComputeSizeForDrawing(imgContainer, ImageResolution(),
|
||||
imageSize, imageRatio, hasWidth,
|
||||
hasHeight);
|
||||
|
||||
// If the image has a fixed width and height, rendering never depends on
|
||||
// the frame size.
|
||||
|
@ -241,17 +241,21 @@ bool SVGImageFrame::GetIntrinsicImageDimensions(
|
||||
return false;
|
||||
}
|
||||
|
||||
ImageResolution resolution = mImageContainer->GetResolution();
|
||||
|
||||
int32_t width, height;
|
||||
if (NS_FAILED(mImageContainer->GetWidth(&width))) {
|
||||
aSize.width = -1;
|
||||
} else {
|
||||
aSize.width = width;
|
||||
resolution.ApplyXTo(aSize.width);
|
||||
}
|
||||
|
||||
if (NS_FAILED(mImageContainer->GetHeight(&height))) {
|
||||
aSize.height = -1;
|
||||
} else {
|
||||
aSize.height = height;
|
||||
resolution.ApplyYTo(aSize.height);
|
||||
}
|
||||
|
||||
Maybe<AspectRatio> asp = mImageContainer->GetIntrinsicRatio();
|
||||
@ -272,6 +276,7 @@ bool SVGImageFrame::TransformContextForPainting(gfxContext* aGfxContext,
|
||||
nativeWidth == 0 || nativeHeight == 0) {
|
||||
return false;
|
||||
}
|
||||
mImageContainer->GetResolution().ApplyTo(nativeWidth, nativeHeight);
|
||||
imageTransform = GetRasterImageTransform(nativeWidth, nativeHeight) *
|
||||
ToMatrix(aTransform);
|
||||
|
||||
@ -405,7 +410,7 @@ void SVGImageFrame::PaintSVG(gfxContext& aContext, const gfxMatrix& aTransform,
|
||||
// That method needs our image to have a fixed native width & height,
|
||||
// and that's not always true for TYPE_VECTOR images.
|
||||
aImgParams.result &= nsLayoutUtils::DrawSingleImage(
|
||||
aContext, PresContext(), mImageContainer, /* aResolution = */ 1.0f,
|
||||
aContext, PresContext(), mImageContainer,
|
||||
nsLayoutUtils::GetSamplingFilterForFrame(this), destRect,
|
||||
aDirtyRect ? dirtyRect : destRect, context, flags);
|
||||
} else { // mImageContainer->GetType() == TYPE_RASTER
|
||||
@ -674,6 +679,7 @@ nsIFrame* SVGImageFrame::GetFrameForPoint(const gfxPoint& aPoint) {
|
||||
nativeWidth == 0 || nativeHeight == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
mImageContainer->GetResolution().ApplyTo(nativeWidth, nativeHeight);
|
||||
Matrix viewBoxTM = SVGContentUtils::GetViewBoxTransform(
|
||||
rect.width, rect.height, 0, 0, nativeWidth, nativeHeight,
|
||||
element->mPreserveAspectRatio);
|
||||
|
@ -240,7 +240,6 @@ void nsImageBoxFrame::UpdateImage() {
|
||||
mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
|
||||
mUseSrcAttr = !src.IsEmpty();
|
||||
if (mUseSrcAttr) {
|
||||
mImageResolution = 1.0f;
|
||||
nsContentPolicyType contentPolicyType;
|
||||
nsCOMPtr<nsIPrincipal> triggeringPrincipal;
|
||||
uint64_t requestContextID = 0;
|
||||
@ -270,9 +269,7 @@ void nsImageBoxFrame::UpdateImage() {
|
||||
}
|
||||
}
|
||||
} else if (auto* styleImage = GetImageFromStyle()) {
|
||||
auto [finalImage, resolution] = styleImage->FinalImageAndResolution();
|
||||
mImageResolution = resolution;
|
||||
if (auto* styleRequest = finalImage->GetImageRequest()) {
|
||||
if (auto* styleRequest = styleImage->GetImageRequest()) {
|
||||
styleRequest->SyncClone(mListener, mContent->GetComposedDoc(),
|
||||
getter_AddRefs(mImageRequest));
|
||||
}
|
||||
@ -394,7 +391,7 @@ ImgDrawResult nsImageBoxFrame::PaintImage(gfxContext& aRenderingContext,
|
||||
Maybe<SVGImageContext> svgContext;
|
||||
SVGImageContext::MaybeStoreContextPaint(svgContext, this, imgCon);
|
||||
return nsLayoutUtils::DrawSingleImage(
|
||||
aRenderingContext, PresContext(), imgCon, mImageResolution,
|
||||
aRenderingContext, PresContext(), imgCon,
|
||||
nsLayoutUtils::GetSamplingFilterForFrame(this), dest, dirty, svgContext,
|
||||
aFlags, anchorPoint.ptrOr(nullptr), hasSubRect ? &mSubRect : nullptr);
|
||||
}
|
||||
@ -610,11 +607,11 @@ bool nsImageBoxFrame::CanOptimizeToImageLayer() {
|
||||
}
|
||||
|
||||
const mozilla::StyleImage* nsImageBoxFrame::GetImageFromStyle(
|
||||
const ComputedStyle& aStyle) {
|
||||
const ComputedStyle& aStyle) const {
|
||||
const nsStyleDisplay* disp = aStyle.StyleDisplay();
|
||||
if (disp->HasAppearance()) {
|
||||
nsPresContext* pc = PresContext();
|
||||
if (pc->Theme()->ThemeSupportsWidget(pc, this,
|
||||
if (pc->Theme()->ThemeSupportsWidget(pc, const_cast<nsImageBoxFrame*>(this),
|
||||
disp->EffectiveAppearance())) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -626,6 +623,21 @@ const mozilla::StyleImage* nsImageBoxFrame::GetImageFromStyle(
|
||||
return ℑ
|
||||
}
|
||||
|
||||
ImageResolution nsImageBoxFrame::GetImageResolution() const {
|
||||
if (auto* image = GetImageFromStyle()) {
|
||||
return image->GetResolution();
|
||||
}
|
||||
if (!mImageRequest) {
|
||||
return {};
|
||||
}
|
||||
nsCOMPtr<imgIContainer> image;
|
||||
mImageRequest->GetImage(getter_AddRefs(image));
|
||||
if (!image) {
|
||||
return {};
|
||||
}
|
||||
return image->GetResolution();
|
||||
}
|
||||
|
||||
/* virtual */
|
||||
void nsImageBoxFrame::DidSetComputedStyle(ComputedStyle* aOldStyle) {
|
||||
nsLeafBoxFrame::DidSetComputedStyle(aOldStyle);
|
||||
@ -803,13 +815,10 @@ void nsImageBoxFrame::OnSizeAvailable(imgIRequest* aRequest,
|
||||
aImage->GetWidth(&w);
|
||||
aImage->GetHeight(&h);
|
||||
|
||||
if (mImageResolution != 0.0f && mImageResolution != 1.0f) {
|
||||
w = std::round(w / mImageResolution);
|
||||
h = std::round(h / mImageResolution);
|
||||
}
|
||||
|
||||
mIntrinsicSize.SizeTo(CSSPixel::ToAppUnits(w), CSSPixel::ToAppUnits(h));
|
||||
|
||||
GetImageResolution().ApplyTo(mIntrinsicSize.width, mIntrinsicSize.height);
|
||||
|
||||
if (!HasAnyStateBits(NS_FRAME_FIRST_REFLOW)) {
|
||||
PresShell()->FrameNeedsReflow(this, IntrinsicDirty::StyleChange,
|
||||
NS_FRAME_IS_DIRTY);
|
||||
|
@ -78,11 +78,13 @@ class nsImageBoxFrame final : public nsLeafBoxFrame {
|
||||
*
|
||||
* TODO(emilio): Maybe support list-style-image: linear-gradient() etc?
|
||||
*/
|
||||
const mozilla::StyleImage* GetImageFromStyle(const ComputedStyle&);
|
||||
const mozilla::StyleImage* GetImageFromStyle() {
|
||||
const mozilla::StyleImage* GetImageFromStyle(const ComputedStyle&) const;
|
||||
const mozilla::StyleImage* GetImageFromStyle() const {
|
||||
return GetImageFromStyle(*Style());
|
||||
}
|
||||
|
||||
mozilla::ImageResolution GetImageResolution() const;
|
||||
|
||||
/**
|
||||
* Update mUseSrcAttr from appropriate content attributes or from
|
||||
* style, throw away the current image, and load the appropriate
|
||||
@ -141,7 +143,6 @@ class nsImageBoxFrame final : public nsLeafBoxFrame {
|
||||
nsSize mImageSize;
|
||||
|
||||
RefPtr<imgRequestProxy> mImageRequest;
|
||||
float mImageResolution = 1.0f;
|
||||
nsCOMPtr<imgINotificationObserver> mListener;
|
||||
|
||||
int32_t mLoadFlags;
|
||||
|
@ -791,12 +791,11 @@ renaming_overrides_prefixing = true
|
||||
|
||||
"GenericImage" = """
|
||||
public:
|
||||
// Returns the final image we've selected taken from the image-set, along with
|
||||
// its resolution, or `this` and `1.0` if this image is not an image-set.
|
||||
// Returns the intrinsic resolution of the image.
|
||||
//
|
||||
// The resolution is in dppx, and should be used to impact the intrinsic size
|
||||
// of the image.
|
||||
std::pair<const StyleGenericImage*, float> FinalImageAndResolution() const;
|
||||
// The resolution is in dppx, and should be used to impact the intrinsic
|
||||
// size of the image.
|
||||
ImageResolution GetResolution() const;
|
||||
|
||||
// Returns the intrinsic size of the image, if there's one, accounting for
|
||||
// resolution as needed.
|
||||
|
@ -0,0 +1 @@
|
||||
prefs: [image.exif-density-correction.enabled:true]
|
@ -1,4 +0,0 @@
|
||||
[density-corrected-image-in-canvas.html]
|
||||
[Density corrected size: canvas]
|
||||
expected: FAIL
|
||||
|
@ -1,2 +0,0 @@
|
||||
[density-corrected-image-svg-aspect-ratio.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[density-corrected-image-svg.html]
|
||||
expected: FAIL
|
@ -1,4 +0,0 @@
|
||||
[density-corrected-natural-size.html]
|
||||
[density-corrected-natural-size]
|
||||
expected: FAIL
|
||||
|
@ -1,2 +0,0 @@
|
||||
[density-corrected-size-bg.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[density-corrected-size-img.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[density-corrected-size-pseudo-elements.html]
|
||||
expected: FAIL
|
@ -1,2 +0,0 @@
|
||||
[density-corrected-various-elements.html]
|
||||
expected: FAIL
|
@ -925,7 +925,7 @@ void PuppetWidget::SetCursor(const Cursor& aCursor) {
|
||||
IntSize customCursorSize;
|
||||
int32_t stride = 0;
|
||||
auto format = SurfaceFormat::B8G8R8A8;
|
||||
float resolution = aCursor.mResolution;
|
||||
ImageResolution resolution = aCursor.mResolution;
|
||||
if (aCursor.IsCustom()) {
|
||||
int32_t width = 0, height = 0;
|
||||
aCursor.mContainer->GetWidth(&width);
|
||||
@ -936,9 +936,8 @@ void PuppetWidget::SetCursor(const Cursor& aCursor) {
|
||||
if (width && height &&
|
||||
aCursor.mContainer->GetType() == imgIContainer::TYPE_VECTOR) {
|
||||
// For vector images, scale to device pixels.
|
||||
resolution *= GetDefaultScale().scale;
|
||||
width = std::ceil(width * resolution);
|
||||
height = std::ceil(height * resolution);
|
||||
resolution.ScaleBy(GetDefaultScale().scale);
|
||||
resolution.ApplyInverseTo(width, height);
|
||||
surface = aCursor.mContainer->GetFrameAtSize(
|
||||
{width, height},
|
||||
imgIContainer::FRAME_CURRENT, flags);
|
||||
@ -964,8 +963,9 @@ void PuppetWidget::SetCursor(const Cursor& aCursor) {
|
||||
length);
|
||||
if (!mBrowserChild->SendSetCursor(
|
||||
aCursor.mDefaultCursor, hasCustomCursor, cursorData,
|
||||
customCursorSize.width, customCursorSize.height, resolution,
|
||||
stride, format, aCursor.mHotspotX, aCursor.mHotspotY, force)) {
|
||||
customCursorSize.width, customCursorSize.height,
|
||||
resolution.mX, resolution.mY, stride, format,
|
||||
aCursor.mHotspotX, aCursor.mHotspotY, force)) {
|
||||
return;
|
||||
}
|
||||
mCursor = aCursor;
|
||||
|
@ -2351,8 +2351,9 @@ static GdkCursor* GetCursorForImage(const nsIWidget::Cursor& aCursor,
|
||||
// factor and then tell gtk to scale it down. We ensure to scale at least to
|
||||
// the GDK scale factor, so that cursors aren't downsized in HiDPI on wayland,
|
||||
// see bug 1707533.
|
||||
int32_t gtkScale =
|
||||
std::max(aWidgetScaleFactor, int32_t(std::ceil(aCursor.mResolution)));
|
||||
int32_t gtkScale = std::max(
|
||||
aWidgetScaleFactor, int32_t(std::ceil(std::max(aCursor.mResolution.mX,
|
||||
aCursor.mResolution.mY))));
|
||||
|
||||
// Reject cursors greater than 128 pixels in some direction, to prevent
|
||||
// spoofing.
|
||||
|
@ -529,10 +529,7 @@ nsIntSize nsIWidget::CustomCursorSize(const Cursor& aCursor) {
|
||||
int32_t height = 0;
|
||||
aCursor.mContainer->GetWidth(&width);
|
||||
aCursor.mContainer->GetHeight(&height);
|
||||
if (aCursor.mResolution != 0.0f && aCursor.mResolution != 1.0f) {
|
||||
width = std::round(float(width) / aCursor.mResolution);
|
||||
height = std::round(float(height) / aCursor.mResolution);
|
||||
}
|
||||
aCursor.mResolution.ApplyTo(width, height);
|
||||
return {width, height};
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "mozilla/layers/LayersTypes.h"
|
||||
#include "mozilla/layers/ScrollableLayerGuid.h"
|
||||
#include "mozilla/layers/ZoomConstraints.h"
|
||||
#include "mozilla/image/Resolution.h"
|
||||
#include "mozilla/widget/IMEData.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsColor.h"
|
||||
@ -992,7 +993,7 @@ class nsIWidget : public nsISupports {
|
||||
nsCOMPtr<imgIContainer> mContainer;
|
||||
uint32_t mHotspotX = 0;
|
||||
uint32_t mHotspotY = 0;
|
||||
float mResolution = 1.0f;
|
||||
mozilla::ImageResolution mResolution;
|
||||
|
||||
bool IsCustom() const { return !!mContainer; }
|
||||
|
||||
@ -1003,7 +1004,7 @@ class nsIWidget : public nsISupports {
|
||||
mResolution == aOther.mResolution;
|
||||
}
|
||||
|
||||
bool operator!=(const Cursor& aOther) { return !(*this == aOther); }
|
||||
bool operator!=(const Cursor& aOther) const { return !(*this == aOther); }
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user