Index: third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp |
diff --git a/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp b/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp |
index 3c1223c6a28e30c2fcd394c988b6f26892aad0e2..2f7e825015e7cd93d8ddf2262b57e9998daa2c51 100644 |
--- a/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp |
+++ b/third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp |
@@ -9,11 +9,11 @@ |
#include "core/dom/ElementRareData.h" |
#include "core/dom/Text.h" |
#include "core/dom/shadow/ShadowRoot.h" |
-#include "core/html/HTMLDivElement.h" |
#include "core/html/HTMLElement.h" |
#include "core/html/HTMLImageElement.h" |
#include "core/html/HTMLImageLoader.h" |
#include "core/html/HTMLInputElement.h" |
+#include "core/html/HTMLSpanElement.h" |
#include "core/html/HTMLStyleElement.h" |
#include "platform/wtf/text/StringBuilder.h" |
@@ -21,31 +21,24 @@ namespace blink { |
using namespace HTMLNames; |
-static bool NoImageSourceSpecified(const Element& element) { |
- bool no_src_specified = !element.hasAttribute(srcAttr) || |
- element.getAttribute(srcAttr).IsNull() || |
- element.getAttribute(srcAttr).IsEmpty(); |
- bool no_srcset_specified = !element.hasAttribute(srcsetAttr) || |
- element.getAttribute(srcsetAttr).IsNull() || |
- element.getAttribute(srcsetAttr).IsEmpty(); |
- return no_src_specified && no_srcset_specified; |
+static bool ImageSmallerThanAltImage(int pixels_for_alt_image, |
+ const Length width, |
+ const Length height) { |
+ // We don't have a layout tree so can't compute the size of an image |
+ // relative dimensions - so we just assume we should display the alt image. |
+ if (!width.IsFixed() && !height.IsFixed()) |
+ return false; |
+ if (height.IsFixed() && height.Value() < pixels_for_alt_image) |
+ return true; |
+ return width.IsFixed() && width.Value() < pixels_for_alt_image; |
} |
void HTMLImageFallbackHelper::CreateAltTextShadowTree(Element& element) { |
ShadowRoot& root = element.EnsureUserAgentShadowRoot(); |
- HTMLDivElement* container = HTMLDivElement::Create(element.GetDocument()); |
+ HTMLSpanElement* container = HTMLSpanElement::Create(element.GetDocument()); |
root.AppendChild(container); |
container->setAttribute(idAttr, AtomicString("alttext-container")); |
- container->SetInlineStyleProperty(CSSPropertyOverflow, CSSValueHidden); |
- container->SetInlineStyleProperty(CSSPropertyBorderWidth, 1, |
- CSSPrimitiveValue::UnitType::kPixels); |
- container->SetInlineStyleProperty(CSSPropertyBorderStyle, CSSValueSolid); |
- container->SetInlineStyleProperty(CSSPropertyBorderColor, CSSValueSilver); |
- container->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueInlineBlock); |
- container->SetInlineStyleProperty(CSSPropertyBoxSizing, CSSValueBorderBox); |
- container->SetInlineStyleProperty(CSSPropertyPadding, 1, |
- CSSPrimitiveValue::UnitType::kPixels); |
HTMLImageElement* broken_image = |
HTMLImageElement::Create(element.GetDocument()); |
@@ -58,11 +51,9 @@ void HTMLImageFallbackHelper::CreateAltTextShadowTree(Element& element) { |
broken_image->SetInlineStyleProperty(CSSPropertyMargin, 0, |
CSSPrimitiveValue::UnitType::kPixels); |
- HTMLDivElement* alt_text = HTMLDivElement::Create(element.GetDocument()); |
+ HTMLSpanElement* alt_text = HTMLSpanElement::Create(element.GetDocument()); |
container->AppendChild(alt_text); |
alt_text->setAttribute(idAttr, AtomicString("alttext")); |
- alt_text->SetInlineStyleProperty(CSSPropertyOverflow, CSSValueHidden); |
- alt_text->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueBlock); |
Text* text = |
Text::Create(element.GetDocument(), ToHTMLElement(element).AltText()); |
@@ -103,36 +94,71 @@ PassRefPtr<ComputedStyle> HTMLImageFallbackHelper::CustomStyleForAltText( |
} |
} |
- // If the image has specified dimensions allow the alt-text container expand |
- // to fill them. |
- if (new_style->Width().IsSpecifiedOrIntrinsic() && |
- new_style->Height().IsSpecifiedOrIntrinsic()) { |
- place_holder->SetInlineStyleProperty( |
- CSSPropertyWidth, 100, CSSPrimitiveValue::UnitType::kPercentage); |
- place_holder->SetInlineStyleProperty( |
- CSSPropertyHeight, 100, CSSPrimitiveValue::UnitType::kPercentage); |
- } |
- |
- // Make sure the broken image icon appears on the appropriate side of the |
- // image for the element's writing direction. |
- broken_image->SetInlineStyleProperty( |
- CSSPropertyFloat, |
- AtomicString(new_style->Direction() == TextDirection::kLtr ? "left" |
- : "right")); |
- |
- // This is an <img> with no attributes, so don't display anything. |
- if (NoImageSourceSpecified(element) && |
- !new_style->Width().IsSpecifiedOrIntrinsic() && |
- !new_style->Height().IsSpecifiedOrIntrinsic() && |
- ToHTMLElement(element).AltText().IsEmpty()) |
- new_style->SetDisplay(EDisplay::kNone); |
- |
- // This preserves legacy behaviour originally defined when alt-text was |
- // managed by LayoutImage. |
- if (NoImageSourceSpecified(element)) |
- broken_image->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); |
- else |
+ bool image_has_intrinsic_dimensions = |
+ new_style->Width().IsSpecifiedOrIntrinsic() && |
+ new_style->Height().IsSpecifiedOrIntrinsic(); |
+ bool image_has_no_alt_attribute = ToHTMLElement(element).AltText().IsNull(); |
+ bool treat_as_replaced = |
+ image_has_intrinsic_dimensions && |
+ (element.GetDocument().InQuirksMode() || image_has_no_alt_attribute); |
+ // 16px for the image and 2px for its top/left border/padding offset. |
+ int pixels_for_alt_image = 18; |
+ if (treat_as_replaced && |
+ !ImageSmallerThanAltImage(pixels_for_alt_image, new_style->Width(), |
+ new_style->Height())) { |
+ // https://html.spec.whatwg.org/multipage/rendering.html#images-3: |
+ // "If the element does not represent an image, but the element already has |
+ // intrinsic dimensions (e.g. from the dimension attributes or CSS rules), |
+ // and either: the user agent has reason to believe that the image will |
+ // become available and be rendered in due course, or the element has no alt |
+ // attribute, or the Document is in quirks mode The user agent is expected |
+ // to treat the element as a replaced element whose content is the text that |
+ // the element represents, if any." |
+ place_holder->SetInlineStyleProperty(CSSPropertyOverflow, CSSValueHidden); |
+ place_holder->SetInlineStyleProperty(CSSPropertyDisplay, |
+ CSSValueInlineBlock); |
+ place_holder->SetInlineStyleProperty(CSSPropertyBorderWidth, 1, |
+ CSSPrimitiveValue::UnitType::kPixels); |
+ place_holder->SetInlineStyleProperty(CSSPropertyBorderStyle, CSSValueSolid); |
+ place_holder->SetInlineStyleProperty(CSSPropertyBorderColor, |
+ CSSValueSilver); |
+ place_holder->SetInlineStyleProperty(CSSPropertyPadding, 1, |
+ CSSPrimitiveValue::UnitType::kPixels); |
+ place_holder->SetInlineStyleProperty(CSSPropertyBoxSizing, |
+ CSSValueBorderBox); |
+ CSSPrimitiveValue::UnitType unit = |
+ new_style->Height().IsPercent() |
+ ? CSSPrimitiveValue::UnitType::kPercentage |
+ : CSSPrimitiveValue::UnitType::kPixels; |
+ place_holder->SetInlineStyleProperty(CSSPropertyHeight, |
+ new_style->Height().Value(), unit); |
+ place_holder->SetInlineStyleProperty(CSSPropertyWidth, |
+ new_style->Width().Value(), unit); |
broken_image->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueInline); |
+ // Make sure the broken image icon appears on the appropriate side of the |
+ // image for the element's writing direction. |
+ broken_image->SetInlineStyleProperty( |
+ CSSPropertyFloat, |
+ AtomicString(new_style->Direction() == TextDirection::kLtr ? "left" |
+ : "right")); |
+ } else { |
+ // "If the element is an img element that represents nothing and the user |
+ // agent does not expect this to change the user agent is expected to treat |
+ // the element as an empty inline element." |
+ // - We achieve this by hiding the broken image so that the span is empty. |
+ // "If the element is an img element that represents some text and the user |
+ // agent does not expect this to change the user agent is expected to treat |
+ // the element as a non-replaced phrasing element whose content is the text, |
+ // optionally with an icon indicating that an image is missing, so that the |
+ // user can request the image be displayed or investigate why it is not |
+ // rendering." |
+ // - We opt not to display an icon, like Firefox. |
+ if (!treat_as_replaced && new_style->Display() == EDisplay::kInline) { |
+ new_style->SetWidth(Length()); |
+ new_style->SetHeight(Length()); |
+ } |
+ broken_image->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); |
+ } |
return new_style; |
} |