Commit bd4c33b5 authored by Luna Lu's avatar Luna Lu Committed by Commit Bot

Add intrinsicsize attribute to HTMLImageElement behind a flag

Design doc: https://docs.google.com/document/d/1yh_-ayeaFV0EjuR51U641zbrPAB0Baqj6UrC9bT9iqQ/edit#heading=h.y7amr11fn0tb

This CL implements "intrinsicsize" attribute for HTMLImageElement.
The value of "intrinsicsize" overrides the intrinsic size:

1. When no width and (or) height is specified, the value of
"intrinsicsize" will be used to determine the area to layout the image
content.

2. natualWidth and naturalHeight will return the density corrected
value of "intrinsicsize".

See explainer: https://github.com/ojanvafai/intrinsicsize-attribute/blob/master/README.md

BUG: 874629
Cq-Include-Trybots: luci.chromium.try:linux_layout_tests_slimming_paint_v2;master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I519f01841ee3e761b22874dbecd74f7e6843e2a9
Reviewed-on: https://chromium-review.googlesource.com/1150725
Commit-Queue: Luna Lu <loonybear@chromium.org>
Reviewed-by: default avatarFredrik Söderquist <fs@opera.com>
Cr-Commit-Position: refs/heads/master@{#587132}
parent 808ee09c
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
'use strict';
const srcs = [
"/feature-policy/experimental-features/resources/image.svg",
"/feature-policy/experimental-features/resources/image.jpg",
"/feature-policy/experimental-features/resources/image.png",
];
for (var src of srcs) {
async_test(t => {
var img = document.createElement('IMG');
img.intrinsicSize = '400 x 500';
var expected_intrinsic_width = 400;
var expected_intrinsic_height = 500;
var expected_width = expected_intrinsic_width;
var expected_height = expected_intrinsic_height;
document.body.appendChild(img);
img.addEventListener('load', t.step_func(() => {
assert_equals(img.width, expected_width, 'width');
assert_equals(img.height, expected_height, 'height');
assert_equals(img.naturalWidth, expected_intrinsic_width, 'naturalWidth');
assert_equals(img.naturalHeight, expected_intrinsic_height, 'naturalHeigh');
t.done();
}));
img.srcset = src + ' 3x';
}, 'Test image ' + src + ' with no specified sizes, width, or height');
async_test(t => {
var img = document.createElement('IMG');
img.intrinsicSize = '400 x 500';
img.width = '800'; /* 2x of intrinsic width */
var expected_intrinsic_width = 400;
var expected_intrinsic_height = 500;
var expected_width = expected_intrinsic_width * 2;
var expected_height = expected_intrinsic_height * 2;
document.body.appendChild(img);
img.addEventListener('load', t.step_func(() => {
assert_equals(img.width, expected_width, 'width');
assert_equals(img.height, expected_height, 'height');
assert_equals(img.naturalWidth, expected_intrinsic_width, 'naturalWidth');
assert_equals(img.naturalHeight, expected_intrinsic_height, 'naturalHeigh');
t.done();
}));
img.srcset = src + ' 3x';
}, 'Test image ' + src + ' with width = 800, no specified sizes, or height');
async_test(t => {
var img = document.createElement('IMG');
img.intrinsicSize = '400 x 500';
img.width = '800';
img.style = 'height:800px;';
var expected_intrinsic_width = 400;
var expected_intrinsic_height = 500;
var expected_width = 800;
var expected_height = 800;
document.body.appendChild(img);
img.addEventListener('load', t.step_func(() => {
assert_equals(img.width, expected_width, 'width');
assert_equals(img.height, expected_height, 'height');
assert_equals(img.naturalWidth, expected_intrinsic_width, 'naturalWidth');
assert_equals(img.naturalHeight, expected_intrinsic_height, 'naturalHeigh');
t.done();
}));
img.srcset = src + ' 3x';
}, 'Test image ' + src + ' with width = 800, height = 800, and no specified sizes');
async_test(t => {
var img = document.createElement('IMG');
img.intrinsicSize = '400 x 500';
img.sizes = '100px';
img.width = '100';
var expected_intrinsic_width = 400;
var expected_intrinsic_height = 500;
var expected_width = 100;
var expected_height = 125;
document.body.appendChild(img);
img.addEventListener('load', t.step_func(() => {
assert_equals(img.width, expected_width, 'width');
assert_equals(img.height, expected_height, 'height');
assert_equals(img.naturalWidth, expected_intrinsic_width, 'naturalWidth');
assert_equals(img.naturalHeight, expected_intrinsic_height, 'naturalHeigh');
t.done();
}));
img.srcset = src + ' 100w';
}, 'Test image ' + src + ' with sizes = 100, width = 100, and srcset descriptor = 100w');
}
</script>
</body>
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
'use strict';
const srcs = [
"/feature-policy/experimental-features/resources/image.svg",
"/feature-policy/experimental-features/resources/image.jpg",
"/feature-policy/experimental-features/resources/image.png",
];
// Wait for a sec for image to repaint before comparing the values.
function updateAttribute(img, attribute, value) {
return new Promise(resolve => {
requestAnimationFrame(() => requestAnimationFrame(() => resolve()));
img.setAttribute(attribute, value);
});
}
for (var src of srcs) {
promise_test(async() => {
var img = document.createElement('IMG');
document.body.appendChild(img);
img.src = src;
await new Promise(resolve => img.addEventListener('load', () => resolve(), {once: true}));
await updateAttribute(img, 'intrinsicSize', '400 x 500');
assert_equals(img.width, 400, 'width');
assert_equals(img.height, 500, 'height');
assert_equals(img.naturalWidth, 400, 'naturalWidth');
assert_equals(img.naturalHeight, 500, 'naturalHeight');
await updateAttribute(img, 'width', '800');
assert_equals(img.width, 800, 'width');
assert_equals(img.height, 1000, 'height');
assert_equals(img.naturalWidth, 400, 'naturalWidth');
assert_equals(img.naturalHeight, 500, 'naturalHeight');
await updateAttribute(img, 'style', 'height:800px;');
assert_equals(img.width, 800, 'width');
assert_equals(img.height, 800, 'height');
assert_equals(img.naturalWidth, 400, 'naturalWidth');
assert_equals(img.naturalHeight, 500, 'naturalHeight');
await updateAttribute(img, 'width', '');
assert_equals(img.width, 640, 'width');
assert_equals(img.height, 800, 'height');
assert_equals(img.naturalWidth, 400, 'naturalWidth');
assert_equals(img.naturalHeight, 500, 'naturalHeight');
await updateAttribute(img, 'style', 'height:800px; writing-mode: vertical-rl;');
assert_equals(img.width, 640, 'width');
assert_equals(img.height, 800, 'height');
assert_equals(img.naturalWidth, 400, 'naturalWidth');
assert_equals(img.naturalHeight, 500, 'naturalHeight');
await updateAttribute(img, 'style', 'height:800px; writing-mode: horizontal-tb;');
assert_equals(img.width, 640, 'width');
assert_equals(img.height, 800, 'height');
assert_equals(img.naturalWidth, 400, 'naturalWidth');
assert_equals(img.naturalHeight, 500, 'naturalHeight');
}, 'Test image with src=' + src);
}
</script>
</body>
<!DOCTYPE html>
<body>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script>
'use strict';
// TODO(loonybear): Once WPT supports tests with page zoom in / out, move this
// test to WPT.
// https://github.com/web-platform-tests/wpt/issues/12725#
const srcs = [
"resources/green.jpg",
"resources/green.png",
"resources/green-circle.svg"
];
const ZOOM_MULTIPLER = 1.2;
function round(n) {
return Math.round(n * 100) / 100;
}
for (var src of srcs) {
var img = document.createElement('IMG');
img.intrinsicSize = '400 x 500';
var intrinsic_width = 400;
var intrinsic_height = 500;
var expected_width = intrinsic_width;
var expected_height = intrinsic_height;
document.body.appendChild(img);
img.addEventListener('load', promise_test(async() => {
if (window.eventSender) {
var expected_dpr = window.devicePixelRatio;
for (var i = 0; i < 3; i++) {
eventSender.zoomPageOut();
expected_width *= ZOOM_MULTIPLER;
expected_height *= ZOOM_MULTIPLER;
expected_dpr /= ZOOM_MULTIPLER;
assert_equals(img.width, Math.round(expected_width), 'width (zoomout)');
assert_equals(img.height, Math.round(expected_height), 'height (zoomout)');
assert_equals(img.naturalWidth, intrinsic_width, 'naturalWidth (zoomout)');
assert_equals(img.naturalHeight, intrinsic_height, 'naturalHeight (zoomout)');
assert_equals(round(window.devicePixelRatio), round(expected_dpr), 'devicePixelRatio');
}
for (var i = 0; i < 3; i++) {
eventSender.zoomPageIn();
expected_width /= ZOOM_MULTIPLER;
expected_height /= ZOOM_MULTIPLER;
expected_dpr *= ZOOM_MULTIPLER;
assert_equals(img.width, Math.round(expected_width), 'width (zoomin)');
assert_equals(img.height, Math.round(expected_height), 'height (zoomin)');
assert_equals(img.naturalWidth, intrinsic_width, 'naturalWidth (zoomin)');
assert_equals(img.naturalHeight, intrinsic_height, 'naturalHeight (zoomin)');
assert_equals(round(window.devicePixelRatio), round(expected_dpr), 'devicePixelRatio');
}
}
}, 'Test image ' + src + 'with different zoom in and zoom out'));
img.src = src;
}
</script>
</body>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="green">
</circle>
</svg>
...@@ -647,6 +647,7 @@ html element img ...@@ -647,6 +647,7 @@ html element img
property height property height
property hspace property hspace
property importance property importance
property intrinsicSize
property isMap property isMap
property longDesc property longDesc
property lowsrc property lowsrc
......
...@@ -2937,6 +2937,7 @@ interface HTMLImageElement : HTMLElement ...@@ -2937,6 +2937,7 @@ interface HTMLImageElement : HTMLElement
getter height getter height
getter hspace getter hspace
getter importance getter importance
getter intrinsicSize
getter isMap getter isMap
getter longDesc getter longDesc
getter lowsrc getter lowsrc
...@@ -2962,6 +2963,7 @@ interface HTMLImageElement : HTMLElement ...@@ -2962,6 +2963,7 @@ interface HTMLImageElement : HTMLElement
setter height setter height
setter hspace setter hspace
setter importance setter importance
setter intrinsicSize
setter isMap setter isMap
setter longDesc setter longDesc
setter lowsrc setter lowsrc
...@@ -3979,6 +3981,7 @@ interface Image ...@@ -3979,6 +3981,7 @@ interface Image
getter height getter height
getter hspace getter hspace
getter importance getter importance
getter intrinsicSize
getter isMap getter isMap
getter longDesc getter longDesc
getter lowsrc getter lowsrc
...@@ -4004,6 +4007,7 @@ interface Image ...@@ -4004,6 +4007,7 @@ interface Image
setter height setter height
setter hspace setter hspace
setter importance setter importance
setter intrinsicSize
setter isMap setter isMap
setter longDesc setter longDesc
setter lowsrc setter lowsrc
......
...@@ -101,6 +101,7 @@ ...@@ -101,6 +101,7 @@
"inert", "inert",
"inputmode", "inputmode",
"integrity", "integrity",
"intrinsicsize",
"is", "is",
"ismap", "ismap",
"keytype", "keytype",
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include "third_party/blink/renderer/core/trustedtypes/trusted_url.h" #include "third_party/blink/renderer/core/trustedtypes/trusted_url.h"
#include "third_party/blink/renderer/platform/network/mime/content_type.h" #include "third_party/blink/renderer/platform/network/mime/content_type.h"
#include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h" #include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h" #include "third_party/blink/renderer/platform/weborigin/security_policy.h"
namespace blink { namespace blink {
...@@ -279,6 +280,10 @@ void HTMLImageElement::ParseAttribute( ...@@ -279,6 +280,10 @@ void HTMLImageElement::ParseAttribute(
} else if (name == decodingAttr) { } else if (name == decodingAttr) {
UseCounter::Count(GetDocument(), WebFeature::kImageDecodingAttribute); UseCounter::Count(GetDocument(), WebFeature::kImageDecodingAttribute);
decoding_mode_ = ParseImageDecodingMode(params.new_value); decoding_mode_ = ParseImageDecodingMode(params.new_value);
} else if (name == intrinsicsizeAttr &&
RuntimeEnabledFeatures::
ExperimentalProductivityFeaturesEnabled()) {
ParseIntrinsicSizeAttribute(params.new_value);
} else { } else {
HTMLElement::ParseAttribute(params); HTMLElement::ParseAttribute(params);
} }
...@@ -477,9 +482,12 @@ unsigned HTMLImageElement::height() { ...@@ -477,9 +482,12 @@ unsigned HTMLImageElement::height() {
} }
LayoutSize HTMLImageElement::DensityCorrectedIntrinsicDimensions() const { LayoutSize HTMLImageElement::DensityCorrectedIntrinsicDimensions() const {
if (!overridden_intrinsic_size_.IsEmpty())
return LayoutSize(overridden_intrinsic_size_);
ImageResourceContent* image_resource = GetImageLoader().GetContent(); ImageResourceContent* image_resource = GetImageLoader().GetContent();
if (!image_resource || !image_resource->HasImage()) if (!image_resource || !image_resource->HasImage())
return LayoutSize(); return LayoutSize();
float pixel_density = image_device_pixel_ratio_; float pixel_density = image_device_pixel_ratio_;
if (image_resource->HasDevicePixelRatioHeaderValue() && if (image_resource->HasDevicePixelRatioHeaderValue() &&
image_resource->DevicePixelRatioHeaderValue() > 0) image_resource->DevicePixelRatioHeaderValue() > 0)
...@@ -487,6 +495,7 @@ LayoutSize HTMLImageElement::DensityCorrectedIntrinsicDimensions() const { ...@@ -487,6 +495,7 @@ LayoutSize HTMLImageElement::DensityCorrectedIntrinsicDimensions() const {
RespectImageOrientationEnum respect_image_orientation = RespectImageOrientationEnum respect_image_orientation =
LayoutObject::ShouldRespectImageOrientation(GetLayoutObject()); LayoutObject::ShouldRespectImageOrientation(GetLayoutObject());
LayoutSize natural_size( LayoutSize natural_size(
image_resource->IntrinsicSize(respect_image_orientation)); image_resource->IntrinsicSize(respect_image_orientation));
natural_size.Scale(pixel_density); natural_size.Scale(pixel_density);
...@@ -558,6 +567,35 @@ void HTMLImageElement::setHeight(unsigned value) { ...@@ -558,6 +567,35 @@ void HTMLImageElement::setHeight(unsigned value) {
SetUnsignedIntegralAttribute(heightAttr, value); SetUnsignedIntegralAttribute(heightAttr, value);
} }
IntSize HTMLImageElement::GetOverriddenIntrinsicSize() const {
return overridden_intrinsic_size_;
}
void HTMLImageElement::ParseIntrinsicSizeAttribute(const String& value) {
unsigned new_width = 0, new_height = 0;
Vector<String> size;
value.Split('x', size);
if (!value.IsEmpty() &&
(size.size() != 2 ||
!ParseHTMLNonNegativeInteger(size.at(0), new_width) ||
!ParseHTMLNonNegativeInteger(size.at(1), new_height))) {
GetDocument().AddConsoleMessage(
ConsoleMessage::Create(kOtherMessageSource, kWarningMessageLevel,
"Unable to parse intrinsicsize: expected "
"[unsigned] x [unsigned], got " +
value));
new_width = 0;
new_height = 0;
}
IntSize new_size(new_width, new_height);
if (overridden_intrinsic_size_ != new_size) {
overridden_intrinsic_size_ = new_size;
if (GetLayoutObject() && GetLayoutObject()->IsLayoutImage())
ToLayoutImage(GetLayoutObject())->IntrinsicSizeChanged();
}
}
KURL HTMLImageElement::Src() const { KURL HTMLImageElement::Src() const {
return GetDocument().CompleteURL(getAttribute(srcAttr)); return GetDocument().CompleteURL(getAttribute(srcAttr));
} }
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "third_party/blink/renderer/core/html/forms/form_associated.h" #include "third_party/blink/renderer/core/html/forms/form_associated.h"
#include "third_party/blink/renderer/core/html/html_element.h" #include "third_party/blink/renderer/core/html/html_element.h"
#include "third_party/blink/renderer/core/html/html_image_loader.h" #include "third_party/blink/renderer/core/html/html_image_loader.h"
#include "third_party/blink/renderer/platform/geometry/int_size.h"
#include "third_party/blink/renderer/platform/graphics/graphics_types.h" #include "third_party/blink/renderer/platform/graphics/graphics_types.h"
#include "third_party/blink/renderer/platform/heap/heap_allocator.h" #include "third_party/blink/renderer/platform/heap/heap_allocator.h"
#include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h"
...@@ -104,6 +105,8 @@ class CORE_EXPORT HTMLImageElement final ...@@ -104,6 +105,8 @@ class CORE_EXPORT HTMLImageElement final
void setWidth(unsigned); void setWidth(unsigned);
IntSize GetOverriddenIntrinsicSize() const;
int x() const; int x() const;
int y() const; int y() const;
...@@ -206,6 +209,8 @@ class CORE_EXPORT HTMLImageElement final ...@@ -206,6 +209,8 @@ class CORE_EXPORT HTMLImageElement final
void NotifyViewportChanged(); void NotifyViewportChanged();
void CreateMediaQueryListIfDoesNotExist(); void CreateMediaQueryListIfDoesNotExist();
void ParseIntrinsicSizeAttribute(const String& value);
Member<HTMLImageLoader> image_loader_; Member<HTMLImageLoader> image_loader_;
Member<ViewportChangeListener> listener_; Member<ViewportChangeListener> listener_;
Member<HTMLFormElement> form_; Member<HTMLFormElement> form_;
...@@ -219,6 +224,8 @@ class CORE_EXPORT HTMLImageElement final ...@@ -219,6 +224,8 @@ class CORE_EXPORT HTMLImageElement final
bool should_invert_color_; bool should_invert_color_;
ReferrerPolicy referrer_policy_; ReferrerPolicy referrer_policy_;
IntSize overridden_intrinsic_size_;
}; };
} // namespace blink } // namespace blink
......
...@@ -42,6 +42,8 @@ ...@@ -42,6 +42,8 @@
[CEReactions, Reflect, ReflectOnly=("","no-referrer","origin","no-referrer-when-downgrade","origin-when-cross-origin","unsafe-url"), ReflectMissing="", ReflectInvalid=""] attribute DOMString referrerPolicy; [CEReactions, Reflect, ReflectOnly=("","no-referrer","origin","no-referrer-when-downgrade","origin-when-cross-origin","unsafe-url"), ReflectMissing="", ReflectInvalid=""] attribute DOMString referrerPolicy;
[CEReactions, Reflect, ReflectOnly=("async", "sync", "auto"), ReflectMissing="auto", ReflectInvalid="auto"] attribute DOMString decoding; [CEReactions, Reflect, ReflectOnly=("async", "sync", "auto"), ReflectMissing="auto", ReflectInvalid="auto"] attribute DOMString decoding;
[CEReactions, RuntimeEnabled=PriorityHints, Reflect, ReflectOnly=("low", "auto", "high"), ReflectMissing="auto", ReflectInvalid="auto"] attribute DOMString importance; [CEReactions, RuntimeEnabled=PriorityHints, Reflect, ReflectOnly=("low", "auto", "high"), ReflectMissing="auto", ReflectInvalid="auto"] attribute DOMString importance;
// https://github.com/ojanvafai/intrinsicsize-attribute/blob/master/README.md
[RuntimeEnabled=ExperimentalProductivityFeatures, CEReactions, Reflect] attribute DOMString intrinsicSize;
// obsolete members // obsolete members
// https://html.spec.whatwg.org/#HTMLImageElement-partial // https://html.spec.whatwg.org/#HTMLImageElement-partial
......
...@@ -182,7 +182,7 @@ void LayoutImage::ImageChanged(WrappedImagePtr new_image, ...@@ -182,7 +182,7 @@ void LayoutImage::ImageChanged(WrappedImagePtr new_image,
if (!did_increment_visually_non_empty_pixel_count_) { if (!did_increment_visually_non_empty_pixel_count_) {
// At a zoom level of 1 the image is guaranteed to have an integer size. // At a zoom level of 1 the image is guaranteed to have an integer size.
View()->GetFrameView()->IncrementVisuallyNonEmptyPixelCount( View()->GetFrameView()->IncrementVisuallyNonEmptyPixelCount(
FlooredIntSize(image_resource_->ImageSize(1.0f))); FlooredIntSize(ImageSizeOverriddenByIntrinsicSize(1.0f)));
did_increment_visually_non_empty_pixel_count_ = true; did_increment_visually_non_empty_pixel_count_ = true;
} }
...@@ -201,8 +201,9 @@ void LayoutImage::UpdateIntrinsicSizeIfNeeded(const LayoutSize& new_size) { ...@@ -201,8 +201,9 @@ void LayoutImage::UpdateIntrinsicSizeIfNeeded(const LayoutSize& new_size) {
void LayoutImage::InvalidatePaintAndMarkForLayoutIfNeeded( void LayoutImage::InvalidatePaintAndMarkForLayoutIfNeeded(
CanDeferInvalidation defer) { CanDeferInvalidation defer) {
LayoutSize old_intrinsic_size = IntrinsicSize(); LayoutSize old_intrinsic_size = IntrinsicSize();
LayoutSize new_intrinsic_size =
RoundedLayoutSize(image_resource_->ImageSize(StyleRef().EffectiveZoom())); LayoutSize new_intrinsic_size = RoundedLayoutSize(
ImageSizeOverriddenByIntrinsicSize(StyleRef().EffectiveZoom()));
UpdateIntrinsicSizeIfNeeded(new_intrinsic_size); UpdateIntrinsicSizeIfNeeded(new_intrinsic_size);
// In the case of generated image content using :before/:after/content, we // In the case of generated image content using :before/:after/content, we
...@@ -368,36 +369,78 @@ bool LayoutImage::NodeAtPoint(HitTestResult& result, ...@@ -368,36 +369,78 @@ bool LayoutImage::NodeAtPoint(HitTestResult& result,
return inside; return inside;
} }
void LayoutImage::ComputeIntrinsicSizingInfo( IntSize LayoutImage::GetOverriddenIntrinsicSize() const {
if (auto* image_element = ToHTMLImageElementOrNull(GetNode())) {
if (RuntimeEnabledFeatures::ExperimentalProductivityFeaturesEnabled())
return image_element->GetOverriddenIntrinsicSize();
}
return IntSize();
}
FloatSize LayoutImage::ImageSizeOverriddenByIntrinsicSize(
float multiplier) const {
FloatSize overridden_intrinsic_size = FloatSize(GetOverriddenIntrinsicSize());
if (overridden_intrinsic_size.IsEmpty())
return image_resource_->ImageSize(multiplier);
if (multiplier != 1) {
overridden_intrinsic_size.Scale(multiplier);
if (overridden_intrinsic_size.Width() < 1.0f)
overridden_intrinsic_size.SetWidth(1.0f);
if (overridden_intrinsic_size.Height() < 1.0f)
overridden_intrinsic_size.SetHeight(1.0f);
}
return overridden_intrinsic_size;
}
bool LayoutImage::OverrideIntrinsicSizingInfo(
IntrinsicSizingInfo& intrinsic_sizing_info) const { IntrinsicSizingInfo& intrinsic_sizing_info) const {
if (SVGImage* svg_image = EmbeddedSVGImage()) { IntSize overridden_intrinsic_size = GetOverriddenIntrinsicSize();
svg_image->GetIntrinsicSizingInfo(intrinsic_sizing_info); if (overridden_intrinsic_size.IsEmpty())
return false;
// Handle zoom & vertical writing modes here, as the embedded SVG document intrinsic_sizing_info.size = FloatSize(overridden_intrinsic_size);
// doesn't know about them. intrinsic_sizing_info.aspect_ratio = intrinsic_sizing_info.size;
intrinsic_sizing_info.size.Scale(StyleRef().EffectiveZoom()); if (!IsHorizontalWritingMode())
if (StyleRef().GetObjectFit() != EObjectFit::kScaleDown) intrinsic_sizing_info.Transpose();
intrinsic_sizing_info.size.Scale(ImageDevicePixelRatio());
if (!IsHorizontalWritingMode()) return true;
intrinsic_sizing_info.Transpose(); }
return;
} void LayoutImage::ComputeIntrinsicSizingInfo(
IntrinsicSizingInfo& intrinsic_sizing_info) const {
if (!OverrideIntrinsicSizingInfo(intrinsic_sizing_info)) {
if (SVGImage* svg_image = EmbeddedSVGImage()) {
svg_image->GetIntrinsicSizingInfo(intrinsic_sizing_info);
// Handle zoom & vertical writing modes here, as the embedded SVG document
// doesn't know about them.
intrinsic_sizing_info.size.Scale(StyleRef().EffectiveZoom());
if (StyleRef().GetObjectFit() != EObjectFit::kScaleDown)
intrinsic_sizing_info.size.Scale(ImageDevicePixelRatio());
if (!IsHorizontalWritingMode())
intrinsic_sizing_info.Transpose();
return;
}
LayoutReplaced::ComputeIntrinsicSizingInfo(intrinsic_sizing_info); LayoutReplaced::ComputeIntrinsicSizingInfo(intrinsic_sizing_info);
// Our intrinsicSize is empty if we're laying out generated images with // Our intrinsicSize is empty if we're laying out generated images with
// relative width/height. Figure out the right intrinsic size to use. // relative width/height. Figure out the right intrinsic size to use.
if (intrinsic_sizing_info.size.IsEmpty() && if (intrinsic_sizing_info.size.IsEmpty() &&
image_resource_->ImageHasRelativeSize() && !IsLayoutNGListMarkerImage()) { image_resource_->ImageHasRelativeSize() &&
LayoutObject* containing_block = !IsLayoutNGListMarkerImage()) {
IsOutOfFlowPositioned() ? Container() : ContainingBlock(); LayoutObject* containing_block =
if (containing_block->IsBox()) { IsOutOfFlowPositioned() ? Container() : ContainingBlock();
LayoutBox* box = ToLayoutBox(containing_block); if (containing_block->IsBox()) {
intrinsic_sizing_info.size.SetWidth( LayoutBox* box = ToLayoutBox(containing_block);
box->AvailableLogicalWidth().ToFloat()); intrinsic_sizing_info.size.SetWidth(
intrinsic_sizing_info.size.SetHeight( box->AvailableLogicalWidth().ToFloat());
box->AvailableLogicalHeight(kIncludeMarginBorderPadding).ToFloat()); intrinsic_sizing_info.size.SetHeight(
box->AvailableLogicalHeight(kIncludeMarginBorderPadding).ToFloat());
}
} }
} }
// Don't compute an intrinsic ratio to preserve historical WebKit behavior if // Don't compute an intrinsic ratio to preserve historical WebKit behavior if
......
...@@ -140,6 +140,11 @@ class CORE_EXPORT LayoutImage : public LayoutReplaced { ...@@ -140,6 +140,11 @@ class CORE_EXPORT LayoutImage : public LayoutReplaced {
void InvalidatePaintAndMarkForLayoutIfNeeded(CanDeferInvalidation); void InvalidatePaintAndMarkForLayoutIfNeeded(CanDeferInvalidation);
void UpdateIntrinsicSizeIfNeeded(const LayoutSize&); void UpdateIntrinsicSizeIfNeeded(const LayoutSize&);
// Override intrinsic sizing info by HTMLImageElement "intrinsicsize"
// attribute if enabled and exists.
bool OverrideIntrinsicSizingInfo(IntrinsicSizingInfo&) const;
FloatSize ImageSizeOverriddenByIntrinsicSize(float multiplier) const;
IntSize GetOverriddenIntrinsicSize() const;
// This member wraps the associated decoded image. // This member wraps the associated decoded image.
// //
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment