Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(634)

Side by Side Diff: third_party/WebKit/Source/core/html/HTMLImageFallbackHelper.cpp

Issue 2593263003: Use a non-replaced inline container for image alt text (Closed)
Patch Set: bug 644802 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "core/html/HTMLImageFallbackHelper.h" 5 #include "core/html/HTMLImageFallbackHelper.h"
6 6
7 #include "core/HTMLNames.h" 7 #include "core/HTMLNames.h"
8 #include "core/InputTypeNames.h" 8 #include "core/InputTypeNames.h"
9 #include "core/dom/ElementRareData.h" 9 #include "core/dom/ElementRareData.h"
10 #include "core/dom/Text.h" 10 #include "core/dom/Text.h"
11 #include "core/dom/shadow/ShadowRoot.h" 11 #include "core/dom/shadow/ShadowRoot.h"
12 #include "core/html/HTMLDivElement.h"
13 #include "core/html/HTMLElement.h" 12 #include "core/html/HTMLElement.h"
14 #include "core/html/HTMLImageElement.h" 13 #include "core/html/HTMLImageElement.h"
15 #include "core/html/HTMLImageLoader.h" 14 #include "core/html/HTMLImageLoader.h"
16 #include "core/html/HTMLInputElement.h" 15 #include "core/html/HTMLInputElement.h"
16 #include "core/html/HTMLSpanElement.h"
17 #include "core/html/HTMLStyleElement.h" 17 #include "core/html/HTMLStyleElement.h"
18 #include "wtf/text/StringBuilder.h" 18 #include "wtf/text/StringBuilder.h"
19 19
20 namespace blink { 20 namespace blink {
21 21
22 using namespace HTMLNames; 22 using namespace HTMLNames;
23 23
24 static bool noImageSourceSpecified(const Element& element) { 24 static bool noImageSourceSpecified(const Element& element) {
25 bool noSrcSpecified = !element.hasAttribute(srcAttr) || 25 bool noSrcSpecified = !element.hasAttribute(srcAttr) ||
26 element.getAttribute(srcAttr).isNull() || 26 element.getAttribute(srcAttr).isNull() ||
27 element.getAttribute(srcAttr).isEmpty(); 27 element.getAttribute(srcAttr).isEmpty();
28 bool noSrcsetSpecified = !element.hasAttribute(srcsetAttr) || 28 bool noSrcsetSpecified = !element.hasAttribute(srcsetAttr) ||
29 element.getAttribute(srcsetAttr).isNull() || 29 element.getAttribute(srcsetAttr).isNull() ||
30 element.getAttribute(srcsetAttr).isEmpty(); 30 element.getAttribute(srcsetAttr).isEmpty();
31 return noSrcSpecified && noSrcsetSpecified; 31 return noSrcSpecified && noSrcsetSpecified;
32 } 32 }
33 33
34 static bool imageSmallerThanAltImage(const Length width, const Length height) {
pdr. 2017/03/14 18:19:27 Can you add a link to the spec text that defines 1
35 if (!width.isFixed() && !height.isFixed())
36 return false;
37 if (height.isFixed())
38 return height.value() < 16;
39 return width.value() < 16;
40 }
41
34 void HTMLImageFallbackHelper::createAltTextShadowTree(Element& element) { 42 void HTMLImageFallbackHelper::createAltTextShadowTree(Element& element) {
35 ShadowRoot& root = element.ensureUserAgentShadowRoot(); 43 ShadowRoot& root = element.ensureUserAgentShadowRoot();
36 44
37 HTMLDivElement* container = HTMLDivElement::create(element.document()); 45 HTMLSpanElement* container = HTMLSpanElement::create(element.document());
38 root.appendChild(container); 46 root.appendChild(container);
39 container->setAttribute(idAttr, AtomicString("alttext-container")); 47 container->setAttribute(idAttr, AtomicString("alttext-container"));
40 container->setInlineStyleProperty(CSSPropertyOverflow, CSSValueHidden);
41 container->setInlineStyleProperty(CSSPropertyBorderWidth, 1,
pdr. 2017/03/14 18:23:27 Does this change match firefox--I still see a bord
42 CSSPrimitiveValue::UnitType::Pixels);
43 container->setInlineStyleProperty(CSSPropertyBorderStyle, CSSValueSolid);
44 container->setInlineStyleProperty(CSSPropertyBorderColor, CSSValueSilver);
45 container->setInlineStyleProperty(CSSPropertyDisplay, CSSValueInlineBlock);
46 container->setInlineStyleProperty(CSSPropertyBoxSizing, CSSValueBorderBox);
47 container->setInlineStyleProperty(CSSPropertyPadding, 1,
48 CSSPrimitiveValue::UnitType::Pixels);
49 48
50 HTMLImageElement* brokenImage = HTMLImageElement::create(element.document()); 49 HTMLImageElement* brokenImage = HTMLImageElement::create(element.document());
51 container->appendChild(brokenImage); 50 container->appendChild(brokenImage);
52 brokenImage->setIsFallbackImage(); 51 brokenImage->setIsFallbackImage();
53 brokenImage->setAttribute(idAttr, AtomicString("alttext-image")); 52 brokenImage->setAttribute(idAttr, AtomicString("alttext-image"));
54 brokenImage->setAttribute(widthAttr, AtomicString("16")); 53 brokenImage->setAttribute(widthAttr, AtomicString("16"));
55 brokenImage->setAttribute(heightAttr, AtomicString("16")); 54 brokenImage->setAttribute(heightAttr, AtomicString("16"));
56 brokenImage->setAttribute(alignAttr, AtomicString("left")); 55 brokenImage->setAttribute(alignAttr, AtomicString("left"));
57 brokenImage->setInlineStyleProperty(CSSPropertyMargin, 0, 56 brokenImage->setInlineStyleProperty(CSSPropertyMargin, 0,
58 CSSPrimitiveValue::UnitType::Pixels); 57 CSSPrimitiveValue::UnitType::Pixels);
59 58
60 HTMLDivElement* altText = HTMLDivElement::create(element.document()); 59 HTMLSpanElement* altText = HTMLSpanElement::create(element.document());
61 container->appendChild(altText); 60 container->appendChild(altText);
62 altText->setAttribute(idAttr, AtomicString("alttext")); 61 altText->setAttribute(idAttr, AtomicString("alttext"));
63 altText->setInlineStyleProperty(CSSPropertyOverflow, CSSValueHidden);
64 altText->setInlineStyleProperty(CSSPropertyDisplay, CSSValueBlock);
65 62
66 Text* text = 63 Text* text =
67 Text::create(element.document(), toHTMLElement(element).altText()); 64 Text::create(element.document(), toHTMLElement(element).altText());
68 altText->appendChild(text); 65 altText->appendChild(text);
69 } 66 }
70 67
71 PassRefPtr<ComputedStyle> HTMLImageFallbackHelper::customStyleForAltText( 68 PassRefPtr<ComputedStyle> HTMLImageFallbackHelper::customStyleForAltText(
72 Element& element, 69 Element& element,
73 PassRefPtr<ComputedStyle> newStyle) { 70 PassRefPtr<ComputedStyle> newStyle) {
74 // If we have an author shadow root or have not created the UA shadow root 71 // If we have an author shadow root or have not created the UA shadow root
(...skipping 20 matching lines...) Expand all
95 else if (newStyle->height().isSpecifiedOrIntrinsic() && 92 else if (newStyle->height().isSpecifiedOrIntrinsic() &&
96 newStyle->width().isAuto()) 93 newStyle->width().isAuto())
97 newStyle->setWidth(newStyle->height()); 94 newStyle->setWidth(newStyle->height());
98 if (newStyle->width().isSpecifiedOrIntrinsic() && 95 if (newStyle->width().isSpecifiedOrIntrinsic() &&
99 newStyle->height().isSpecifiedOrIntrinsic()) { 96 newStyle->height().isSpecifiedOrIntrinsic()) {
100 placeHolder->setInlineStyleProperty(CSSPropertyVerticalAlign, 97 placeHolder->setInlineStyleProperty(CSSPropertyVerticalAlign,
101 CSSValueBaseline); 98 CSSValueBaseline);
102 } 99 }
103 } 100 }
104 101
105 // If the image has specified dimensions allow the alt-text container expand 102 bool imageHasIntrinsicDimensions =
106 // to fill them. 103 newStyle->width().isSpecifiedOrIntrinsic() &&
107 if (newStyle->width().isSpecifiedOrIntrinsic() && 104 newStyle->height().isSpecifiedOrIntrinsic();
108 newStyle->height().isSpecifiedOrIntrinsic()) { 105 bool imageHasNoAltAttribute = toHTMLElement(element).altText().isNull();
109 placeHolder->setInlineStyleProperty( 106 bool imageHasEmptyAltAttribute =
110 CSSPropertyWidth, 100, CSSPrimitiveValue::UnitType::Percentage); 107 !imageHasNoAltAttribute && toHTMLElement(element).altText().isEmpty();
111 placeHolder->setInlineStyleProperty( 108 bool imageHasSrcAttribute = !noImageSourceSpecified(element);
112 CSSPropertyHeight, 100, CSSPrimitiveValue::UnitType::Percentage); 109
110 // https://html.spec.whatwg.org/multipage/embedded-content.html#the-img-elemen t
111 enum ElementRepresents { ElementRepresentsNothing, ElementRepresentsText };
112 ElementRepresents elementRepresents = ElementRepresentsText;
113 if (imageHasSrcAttribute && imageHasEmptyAltAttribute) {
114 // First case: "If the src attribute is set and the alt attribute is set to
115 // the empty string ... the element represents nothing ..."
116 elementRepresents = ElementRepresentsNothing;
117 } else if (!imageHasSrcAttribute &&
118 (imageHasNoAltAttribute || imageHasEmptyAltAttribute)) {
119 // Fourth case: "If the src attribute is not set and either the alt
120 // attribute is set to the empty string or the alt attribute is not set at
121 // all ... The element represents nothing."
122 elementRepresents = ElementRepresentsNothing;
123 }
124
125 // https://html.spec.whatwg.org/multipage/rendering.html#images-3:
126 // "If the element does not represent an image, but the element already has
127 // intrinsic dimensions (e.g. from the dimension attributes or CSS rules), and
128 // either: the user agent has reason to believe that the image will become
129 // available and be rendered in due course, or the element has no alt
130 // attribute, or the Document is in quirks mode The user agent is expected to
131 // treat the element as a replaced element whose content is the text that the
132 // element represents, if any."
133 bool treatAsReplaced =
134 imageHasIntrinsicDimensions &&
135 (element.document().inQuirksMode() || imageHasNoAltAttribute);
136 if (!treatAsReplaced && newStyle->display() == EDisplay::Inline) {
137 newStyle->setWidth(Length());
138 newStyle->setHeight(Length());
113 } 139 }
114 140
115 // Make sure the broken image icon appears on the appropriate side of the 141 // Make sure the broken image icon appears on the appropriate side of the
116 // image for the element's writing direction. 142 // image for the element's writing direction.
117 brokenImage->setInlineStyleProperty( 143 brokenImage->setInlineStyleProperty(
118 CSSPropertyFloat, 144 CSSPropertyFloat,
119 AtomicString(newStyle->direction() == TextDirection::kLtr ? "left" 145 AtomicString(newStyle->direction() == TextDirection::kLtr ? "left"
120 : "right")); 146 : "right"));
121 147
122 // This is an <img> with no attributes, so don't display anything. 148 if (elementRepresents == ElementRepresentsNothing ||
123 if (noImageSourceSpecified(element) && 149 imageSmallerThanAltImage(newStyle->width(), newStyle->height())) {
124 !newStyle->width().isSpecifiedOrIntrinsic() && 150 // "If the element is an img element that represents nothing and the user
pdr. 2017/03/14 18:19:27 This seems like a significant change. I think this
rhogan 2017/03/23 12:24:44 Do you mean not displaying the alt image icon if t
125 !newStyle->height().isSpecifiedOrIntrinsic() && 151 // agent does not expect this to change the user agent is expected to treat
126 toHTMLElement(element).altText().isEmpty()) 152 // the element as an empty inline element."
127 newStyle->setDisplay(EDisplay::None); 153 // We achieve this by hiding the broken image so that the span is empty.
128
129 // This preserves legacy behaviour originally defined when alt-text was
130 // managed by LayoutImage.
131 if (noImageSourceSpecified(element))
132 brokenImage->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone); 154 brokenImage->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
133 else 155 } else {
156 // "If the element is an img element that represents some text and the user
157 // agent does not expect this to change the user agent is expected to treat
158 // the element as a non-replaced phrasing element whose content is the text,
159 // optionally with an icon indicating that an image is missing, so that the
160 // user can request the image be displayed or investigate why it is not
161 // rendering."
134 brokenImage->setInlineStyleProperty(CSSPropertyDisplay, CSSValueInline); 162 brokenImage->setInlineStyleProperty(CSSPropertyDisplay, CSSValueInline);
163 }
135 164
136 return newStyle; 165 return newStyle;
137 } 166 }
138 167
139 } // namespace blink 168 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698