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

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: Use a non-replaced inline container for image alt text Created 3 years, 8 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 "platform/wtf/text/StringBuilder.h" 18 #include "platform/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 ImageSmallerThanAltImage(int pixels_for_alt_image,
25 bool no_src_specified = !element.hasAttribute(srcAttr) || 25 const Length width,
26 element.getAttribute(srcAttr).IsNull() || 26 const Length height) {
27 element.getAttribute(srcAttr).IsEmpty(); 27 // We don't have a layout tree so can't compute the size of an image
28 bool no_srcset_specified = !element.hasAttribute(srcsetAttr) || 28 // relative dimensions - so we just assume we should display the alt image.
29 element.getAttribute(srcsetAttr).IsNull() || 29 if (!width.IsFixed() && !height.IsFixed())
30 element.getAttribute(srcsetAttr).IsEmpty(); 30 return false;
31 return no_src_specified && no_srcset_specified; 31 if (height.IsFixed() && height.Value() < pixels_for_alt_image)
32 return true;
33 return width.IsFixed() && width.Value() < pixels_for_alt_image;
32 } 34 }
33 35
34 void HTMLImageFallbackHelper::CreateAltTextShadowTree(Element& element) { 36 void HTMLImageFallbackHelper::CreateAltTextShadowTree(Element& element) {
35 ShadowRoot& root = element.EnsureUserAgentShadowRoot(); 37 ShadowRoot& root = element.EnsureUserAgentShadowRoot();
36 38
37 HTMLDivElement* container = HTMLDivElement::Create(element.GetDocument()); 39 HTMLSpanElement* container = HTMLSpanElement::Create(element.GetDocument());
38 root.AppendChild(container); 40 root.AppendChild(container);
39 container->setAttribute(idAttr, AtomicString("alttext-container")); 41 container->setAttribute(idAttr, AtomicString("alttext-container"));
40 container->SetInlineStyleProperty(CSSPropertyOverflow, CSSValueHidden);
41 container->SetInlineStyleProperty(CSSPropertyBorderWidth, 1,
42 CSSPrimitiveValue::UnitType::kPixels);
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::kPixels);
49 42
50 HTMLImageElement* broken_image = 43 HTMLImageElement* broken_image =
51 HTMLImageElement::Create(element.GetDocument()); 44 HTMLImageElement::Create(element.GetDocument());
52 container->AppendChild(broken_image); 45 container->AppendChild(broken_image);
53 broken_image->SetIsFallbackImage(); 46 broken_image->SetIsFallbackImage();
54 broken_image->setAttribute(idAttr, AtomicString("alttext-image")); 47 broken_image->setAttribute(idAttr, AtomicString("alttext-image"));
55 broken_image->setAttribute(widthAttr, AtomicString("16")); 48 broken_image->setAttribute(widthAttr, AtomicString("16"));
56 broken_image->setAttribute(heightAttr, AtomicString("16")); 49 broken_image->setAttribute(heightAttr, AtomicString("16"));
57 broken_image->setAttribute(alignAttr, AtomicString("left")); 50 broken_image->setAttribute(alignAttr, AtomicString("left"));
58 broken_image->SetInlineStyleProperty(CSSPropertyMargin, 0, 51 broken_image->SetInlineStyleProperty(CSSPropertyMargin, 0,
59 CSSPrimitiveValue::UnitType::kPixels); 52 CSSPrimitiveValue::UnitType::kPixels);
60 53
61 HTMLDivElement* alt_text = HTMLDivElement::Create(element.GetDocument()); 54 HTMLSpanElement* alt_text = HTMLSpanElement::Create(element.GetDocument());
62 container->AppendChild(alt_text); 55 container->AppendChild(alt_text);
63 alt_text->setAttribute(idAttr, AtomicString("alttext")); 56 alt_text->setAttribute(idAttr, AtomicString("alttext"));
64 alt_text->SetInlineStyleProperty(CSSPropertyOverflow, CSSValueHidden);
65 alt_text->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueBlock);
66 57
67 Text* text = 58 Text* text =
68 Text::Create(element.GetDocument(), ToHTMLElement(element).AltText()); 59 Text::Create(element.GetDocument(), ToHTMLElement(element).AltText());
69 alt_text->AppendChild(text); 60 alt_text->AppendChild(text);
70 } 61 }
71 62
72 PassRefPtr<ComputedStyle> HTMLImageFallbackHelper::CustomStyleForAltText( 63 PassRefPtr<ComputedStyle> HTMLImageFallbackHelper::CustomStyleForAltText(
73 Element& element, 64 Element& element,
74 PassRefPtr<ComputedStyle> new_style) { 65 PassRefPtr<ComputedStyle> new_style) {
75 // If we have an author shadow root or have not created the UA shadow root 66 // If we have an author shadow root or have not created the UA shadow root
(...skipping 20 matching lines...) Expand all
96 else if (new_style->Height().IsSpecifiedOrIntrinsic() && 87 else if (new_style->Height().IsSpecifiedOrIntrinsic() &&
97 new_style->Width().IsAuto()) 88 new_style->Width().IsAuto())
98 new_style->SetWidth(new_style->Height()); 89 new_style->SetWidth(new_style->Height());
99 if (new_style->Width().IsSpecifiedOrIntrinsic() && 90 if (new_style->Width().IsSpecifiedOrIntrinsic() &&
100 new_style->Height().IsSpecifiedOrIntrinsic()) { 91 new_style->Height().IsSpecifiedOrIntrinsic()) {
101 place_holder->SetInlineStyleProperty(CSSPropertyVerticalAlign, 92 place_holder->SetInlineStyleProperty(CSSPropertyVerticalAlign,
102 CSSValueBaseline); 93 CSSValueBaseline);
103 } 94 }
104 } 95 }
105 96
106 // If the image has specified dimensions allow the alt-text container expand 97 bool image_has_intrinsic_dimensions =
107 // to fill them. 98 new_style->Width().IsSpecifiedOrIntrinsic() &&
108 if (new_style->Width().IsSpecifiedOrIntrinsic() && 99 new_style->Height().IsSpecifiedOrIntrinsic();
109 new_style->Height().IsSpecifiedOrIntrinsic()) { 100 bool image_has_no_alt_attribute = ToHTMLElement(element).AltText().IsNull();
110 place_holder->SetInlineStyleProperty( 101 bool treat_as_replaced =
111 CSSPropertyWidth, 100, CSSPrimitiveValue::UnitType::kPercentage); 102 image_has_intrinsic_dimensions &&
112 place_holder->SetInlineStyleProperty( 103 (element.GetDocument().InQuirksMode() || image_has_no_alt_attribute);
113 CSSPropertyHeight, 100, CSSPrimitiveValue::UnitType::kPercentage); 104 // 16px for the image and 2px for its top/left border/padding offset.
105 int pixels_for_alt_image = 18;
106 if (treat_as_replaced &&
107 !ImageSmallerThanAltImage(pixels_for_alt_image, new_style->Width(),
108 new_style->Height())) {
109 // https://html.spec.whatwg.org/multipage/rendering.html#images-3:
110 // "If the element does not represent an image, but the element already has
111 // intrinsic dimensions (e.g. from the dimension attributes or CSS rules),
112 // and either: the user agent has reason to believe that the image will
113 // become available and be rendered in due course, or the element has no alt
114 // attribute, or the Document is in quirks mode The user agent is expected
115 // to treat the element as a replaced element whose content is the text that
116 // the element represents, if any."
117 place_holder->SetInlineStyleProperty(CSSPropertyOverflow, CSSValueHidden);
118 place_holder->SetInlineStyleProperty(CSSPropertyDisplay,
119 CSSValueInlineBlock);
120 place_holder->SetInlineStyleProperty(CSSPropertyBorderWidth, 1,
121 CSSPrimitiveValue::UnitType::kPixels);
122 place_holder->SetInlineStyleProperty(CSSPropertyBorderStyle, CSSValueSolid);
123 place_holder->SetInlineStyleProperty(CSSPropertyBorderColor,
124 CSSValueSilver);
125 place_holder->SetInlineStyleProperty(CSSPropertyPadding, 1,
126 CSSPrimitiveValue::UnitType::kPixels);
127 place_holder->SetInlineStyleProperty(CSSPropertyBoxSizing,
128 CSSValueBorderBox);
129 CSSPrimitiveValue::UnitType unit =
130 new_style->Height().IsPercent()
131 ? CSSPrimitiveValue::UnitType::kPercentage
132 : CSSPrimitiveValue::UnitType::kPixels;
133 place_holder->SetInlineStyleProperty(CSSPropertyHeight,
134 new_style->Height().Value(), unit);
135 place_holder->SetInlineStyleProperty(CSSPropertyWidth,
136 new_style->Width().Value(), unit);
137 broken_image->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueInline);
138 // Make sure the broken image icon appears on the appropriate side of the
139 // image for the element's writing direction.
140 broken_image->SetInlineStyleProperty(
141 CSSPropertyFloat,
142 AtomicString(new_style->Direction() == TextDirection::kLtr ? "left"
143 : "right"));
144 } else {
145 // "If the element is an img element that represents nothing and the user
146 // agent does not expect this to change the user agent is expected to treat
147 // the element as an empty inline element."
148 // - We achieve this by hiding the broken image so that the span is empty.
149 // "If the element is an img element that represents some text and the user
150 // agent does not expect this to change the user agent is expected to treat
151 // the element as a non-replaced phrasing element whose content is the text,
152 // optionally with an icon indicating that an image is missing, so that the
153 // user can request the image be displayed or investigate why it is not
154 // rendering."
155 // - We opt not to display an icon, like Firefox.
156 if (!treat_as_replaced && new_style->Display() == EDisplay::kInline) {
157 new_style->SetWidth(Length());
158 new_style->SetHeight(Length());
159 }
160 broken_image->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
114 } 161 }
115 162
116 // Make sure the broken image icon appears on the appropriate side of the
117 // image for the element's writing direction.
118 broken_image->SetInlineStyleProperty(
119 CSSPropertyFloat,
120 AtomicString(new_style->Direction() == TextDirection::kLtr ? "left"
121 : "right"));
122
123 // This is an <img> with no attributes, so don't display anything.
124 if (NoImageSourceSpecified(element) &&
125 !new_style->Width().IsSpecifiedOrIntrinsic() &&
126 !new_style->Height().IsSpecifiedOrIntrinsic() &&
127 ToHTMLElement(element).AltText().IsEmpty())
128 new_style->SetDisplay(EDisplay::kNone);
129
130 // This preserves legacy behaviour originally defined when alt-text was
131 // managed by LayoutImage.
132 if (NoImageSourceSpecified(element))
133 broken_image->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueNone);
134 else
135 broken_image->SetInlineStyleProperty(CSSPropertyDisplay, CSSValueInline);
136
137 return new_style; 163 return new_style;
138 } 164 }
139 165
140 } // namespace blink 166 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698