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

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
« no previous file with comments | « third_party/WebKit/LayoutTests/platform/linux/images/rendering-broken-block-flow-images-expected.png ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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) {
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,
42 CSSPrimitiveValue::UnitType::Pixels);
43 container->setInlineStyleProperty(CSSPropertyBorderStyle, CSSValueSolid);
44 container->setInlineStyleProperty(CSSPropertyBorderColor, CSSValueSilver);
45 container->setInlineStyleProperty(CSSPropertyDisplay, CSSValueInlineBlock);
pdr. 2017/03/02 21:51:11 I looked at https://chromium.googlesource.com/chro
rhogan 2017/03/02 23:44:46 Because it gave the nearest rendering to the way w
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 imageHasNoSrcAttribute = 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;
113 if (!imageHasNoSrcAttribute && imageHasEmptyAltAttribute)
pdr. 2017/03/02 21:51:11 This is hard to follow. I think this if-else chain
rhogan 2017/03/02 23:44:46 Agreed. In its favour though it implements the log
pdr. 2017/03/03 00:52:06 Ahh, I see what you mean. This does nicely follow
114 elementRepresents = ElementRepresentsNothing;
115 else if (!imageHasNoSrcAttribute && !imageHasEmptyAltAttribute &&
116 !imageHasNoAltAttribute)
117 elementRepresents = ElementRepresentsText;
118 else if (!imageHasNoSrcAttribute && imageHasNoAltAttribute)
119 elementRepresents = ElementRepresentsText;
pdr. 2017/03/02 21:51:11 Can this ever be hit since imageHasEmptyAltAttribu
rhogan 2017/03/02 23:44:46 Yes, I think so: where <img src="test.jpg">. The p
pdr. 2017/03/03 00:52:06 Yeah I think it might be a little easier to read u
120 else if (imageHasNoSrcAttribute &&
121 (imageHasNoAltAttribute || imageHasEmptyAltAttribute))
122 elementRepresents = ElementRepresentsNothing;
123 else
124 elementRepresents = ElementRepresentsText;
125
126 // https://html.spec.whatwg.org/multipage/rendering.html#images-3:
127 // "If the element does not represent an image, but the element already has
128 // intrinsic dimensions (e.g. from the dimension attributes or CSS rules), and
129 // either: the user agent has reason to believe that the image will become
130 // available and be rendered in due course, or the element has no alt
131 // attribute, or the Document is in quirks mode The user agent is expected to
132 // treat the element as a replaced element whose content is the text that the
133 // element represents, if any."
134 bool treatAsReplaced =
135 imageHasIntrinsicDimensions &&
136 (element.document().inQuirksMode() || imageHasNoAltAttribute);
137 if (!treatAsReplaced && newStyle->display() == EDisplay::Inline) {
138 newStyle->setWidth(Length());
139 newStyle->setHeight(Length());
113 } 140 }
114 141
115 // Make sure the broken image icon appears on the appropriate side of the 142 // Make sure the broken image icon appears on the appropriate side of the
116 // image for the element's writing direction. 143 // image for the element's writing direction.
117 brokenImage->setInlineStyleProperty( 144 brokenImage->setInlineStyleProperty(
118 CSSPropertyFloat, 145 CSSPropertyFloat,
119 AtomicString(newStyle->direction() == TextDirection::kLtr ? "left" 146 AtomicString(newStyle->direction() == TextDirection::kLtr ? "left"
120 : "right")); 147 : "right"));
121 148
122 // This is an <img> with no attributes, so don't display anything. 149 if (elementRepresents == ElementRepresentsNothing ||
123 if (noImageSourceSpecified(element) && 150 imageSmallerThanAltImage(newStyle->width(), newStyle->height())) {
pdr. 2017/03/02 21:51:11 Can this imageSmallerThanAltImage logic be combine
rhogan 2017/03/02 23:44:46 Sure, makes sense - it's blink-specific rather tha
124 !newStyle->width().isSpecifiedOrIntrinsic() && 151 // "If the element is an img element that represents nothing and the user
125 !newStyle->height().isSpecifiedOrIntrinsic() && 152 // agent does not expect this to change the user agent is expected to treat
126 toHTMLElement(element).altText().isEmpty()) 153 // the element as an empty inline element."
127 newStyle->setDisplay(EDisplay::None); 154 // 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); 155 brokenImage->setInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
133 else 156 } else {
157 // "If the element is an img element that represents some text and the user
158 // agent does not expect this to change the user agent is expected to treat
159 // the element as a non-replaced phrasing element whose content is the text,
160 // optionally with an icon indicating that an image is missing, so that the
161 // user can request the image be displayed or investigate why it is not
162 // rendering."
134 brokenImage->setInlineStyleProperty(CSSPropertyDisplay, CSSValueInline); 163 brokenImage->setInlineStyleProperty(CSSPropertyDisplay, CSSValueInline);
164 }
135 165
136 return newStyle; 166 return newStyle;
137 } 167 }
138 168
139 } // namespace blink 169 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/LayoutTests/platform/linux/images/rendering-broken-block-flow-images-expected.png ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698