OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) | 2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org) |
3 * (C) 1999 Antti Koivisto (koivisto@kde.org) | 3 * (C) 1999 Antti Koivisto (koivisto@kde.org) |
4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserv
ed. | 4 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserv
ed. |
5 * Copyright (C) 2010 Google Inc. All rights reserved. | 5 * Copyright (C) 2010 Google Inc. All rights reserved. |
6 * | 6 * |
7 * This library is free software; you can redistribute it and/or | 7 * This library is free software; you can redistribute it and/or |
8 * modify it under the terms of the GNU Library General Public | 8 * modify it under the terms of the GNU Library General Public |
9 * License as published by the Free Software Foundation; either | 9 * License as published by the Free Software Foundation; either |
10 * version 2 of the License, or (at your option) any later version. | 10 * version 2 of the License, or (at your option) any later version. |
(...skipping 19 matching lines...) Expand all Loading... |
30 #include "core/css/MediaQueryMatcher.h" | 30 #include "core/css/MediaQueryMatcher.h" |
31 #include "core/css/MediaValuesDynamic.h" | 31 #include "core/css/MediaValuesDynamic.h" |
32 #include "core/css/parser/SizesAttributeParser.h" | 32 #include "core/css/parser/SizesAttributeParser.h" |
33 #include "core/dom/Attribute.h" | 33 #include "core/dom/Attribute.h" |
34 #include "core/dom/NodeTraversal.h" | 34 #include "core/dom/NodeTraversal.h" |
35 #include "core/fetch/ImageResource.h" | 35 #include "core/fetch/ImageResource.h" |
36 #include "core/frame/UseCounter.h" | 36 #include "core/frame/UseCounter.h" |
37 #include "core/html/HTMLAnchorElement.h" | 37 #include "core/html/HTMLAnchorElement.h" |
38 #include "core/html/HTMLCanvasElement.h" | 38 #include "core/html/HTMLCanvasElement.h" |
39 #include "core/html/HTMLFormElement.h" | 39 #include "core/html/HTMLFormElement.h" |
| 40 #include "core/html/HTMLImageFallbackHelper.h" |
40 #include "core/html/HTMLSourceElement.h" | 41 #include "core/html/HTMLSourceElement.h" |
41 #include "core/html/canvas/CanvasRenderingContext.h" | 42 #include "core/html/canvas/CanvasRenderingContext.h" |
42 #include "core/html/parser/HTMLParserIdioms.h" | 43 #include "core/html/parser/HTMLParserIdioms.h" |
43 #include "core/html/parser/HTMLSrcsetParser.h" | 44 #include "core/html/parser/HTMLSrcsetParser.h" |
44 #include "core/inspector/ConsoleMessage.h" | 45 #include "core/inspector/ConsoleMessage.h" |
| 46 #include "core/rendering/RenderBlockFlow.h" |
45 #include "core/rendering/RenderImage.h" | 47 #include "core/rendering/RenderImage.h" |
46 #include "platform/MIMETypeRegistry.h" | 48 #include "platform/MIMETypeRegistry.h" |
47 #include "platform/RuntimeEnabledFeatures.h" | 49 #include "platform/RuntimeEnabledFeatures.h" |
48 | 50 |
49 namespace blink { | 51 namespace blink { |
50 | 52 |
51 using namespace HTMLNames; | 53 using namespace HTMLNames; |
52 | 54 |
53 class HTMLImageElement::ViewportChangeListener FINAL : public MediaQueryListList
ener { | 55 class HTMLImageElement::ViewportChangeListener FINAL : public MediaQueryListList
ener { |
54 public: | 56 public: |
(...skipping 17 matching lines...) Expand all Loading... |
72 MediaQueryListListener::trace(visitor); | 74 MediaQueryListListener::trace(visitor); |
73 } | 75 } |
74 private: | 76 private: |
75 explicit ViewportChangeListener(HTMLImageElement* element) : m_element(eleme
nt) { } | 77 explicit ViewportChangeListener(HTMLImageElement* element) : m_element(eleme
nt) { } |
76 RawPtrWillBeMember<HTMLImageElement> m_element; | 78 RawPtrWillBeMember<HTMLImageElement> m_element; |
77 }; | 79 }; |
78 | 80 |
79 HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form, bo
ol createdByParser) | 81 HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form, bo
ol createdByParser) |
80 : HTMLElement(imgTag, document) | 82 : HTMLElement(imgTag, document) |
81 , m_imageLoader(HTMLImageLoader::create(this)) | 83 , m_imageLoader(HTMLImageLoader::create(this)) |
| 84 , m_altTextNode(0) |
82 , m_compositeOperator(CompositeSourceOver) | 85 , m_compositeOperator(CompositeSourceOver) |
83 , m_imageDevicePixelRatio(1.0f) | 86 , m_imageDevicePixelRatio(1.0f) |
84 , m_formWasSetByParser(false) | 87 , m_formWasSetByParser(false) |
85 , m_elementCreatedByParser(createdByParser) | 88 , m_elementCreatedByParser(createdByParser) |
86 , m_intrinsicSizingViewportDependant(false) | 89 , m_intrinsicSizingViewportDependant(false) |
87 , m_effectiveSizeViewportDependant(false) | 90 , m_effectiveSizeViewportDependant(false) |
| 91 , m_useFallbackContent(false) |
| 92 , m_isFallbackImage(false) |
88 { | 93 { |
89 ScriptWrappable::init(this); | 94 ScriptWrappable::init(this); |
| 95 setHasCustomStyleCallbacks(); |
90 if (form && form->inDocument()) { | 96 if (form && form->inDocument()) { |
91 #if ENABLE(OILPAN) | 97 #if ENABLE(OILPAN) |
92 m_form = form; | 98 m_form = form; |
93 #else | 99 #else |
94 m_form = form->createWeakPtr(); | 100 m_form = form->createWeakPtr(); |
95 #endif | 101 #endif |
96 m_formWasSetByParser = true; | 102 m_formWasSetByParser = true; |
97 m_form->associate(*this); | 103 m_form->associate(*this); |
98 m_form->didAssociateByParser(); | 104 m_form->didAssociateByParser(); |
99 } | 105 } |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 UseCounter::count(document(), UseCounter::SrcsetWDescriptor); | 236 UseCounter::count(document(), UseCounter::SrcsetWDescriptor); |
231 } else if (!candidate.srcOrigin()) { | 237 } else if (!candidate.srcOrigin()) { |
232 UseCounter::count(document(), UseCounter::SrcsetXDescriptor); | 238 UseCounter::count(document(), UseCounter::SrcsetXDescriptor); |
233 } | 239 } |
234 if (renderer() && renderer()->isImage()) | 240 if (renderer() && renderer()->isImage()) |
235 toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePixelRa
tio); | 241 toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePixelRa
tio); |
236 } | 242 } |
237 | 243 |
238 void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) | 244 void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) |
239 { | 245 { |
240 if (name == altAttr) { | 246 if (name == altAttr || name == titleAttr) { |
241 if (renderer() && renderer()->isImage()) | 247 if (Text* text = altTextNode()) { |
242 toRenderImage(renderer())->updateAltText(); | 248 String alt = altText(); |
| 249 if (text->data() != alt) |
| 250 text->setData(alt); |
| 251 } |
243 } else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) { | 252 } else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) { |
244 selectSourceURL(ImageLoader::UpdateIgnorePreviousError); | 253 selectSourceURL(ImageLoader::UpdateIgnorePreviousError); |
245 } else if (name == usemapAttr) { | 254 } else if (name == usemapAttr) { |
246 setIsLink(!value.isNull()); | 255 setIsLink(!value.isNull()); |
247 } else if (name == compositeAttr) { | 256 } else if (name == compositeAttr) { |
248 blink::WebBlendMode blendOp = blink::WebBlendModeNormal; | 257 blink::WebBlendMode blendOp = blink::WebBlendModeNormal; |
249 if (!parseCompositeAndBlendOperator(value, m_compositeOperator, blendOp)
) | 258 if (!parseCompositeAndBlendOperator(value, m_compositeOperator, blendOp)
) |
250 m_compositeOperator = CompositeSourceOver; | 259 m_compositeOperator = CompositeSourceOver; |
251 else if (m_compositeOperator != CompositeSourceOver) | 260 else if (m_compositeOperator != CompositeSourceOver) |
252 UseCounter::count(document(), UseCounter::HTMLImageElementComposite)
; | 261 UseCounter::count(document(), UseCounter::HTMLImageElementComposite)
; |
253 } else { | 262 } else { |
254 HTMLElement::parseAttribute(name, value); | 263 HTMLElement::parseAttribute(name, value); |
255 } | 264 } |
256 } | 265 } |
257 | 266 |
258 const AtomicString& HTMLImageElement::altText() const | 267 String HTMLImageElement::altText() const |
259 { | 268 { |
260 // lets figure out the alt text.. magic stuff | 269 // lets figure out the alt text.. magic stuff |
261 // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen | 270 // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen |
262 // also heavily discussed by Hixie on bugzilla | 271 // also heavily discussed by Hixie on bugzilla |
263 const AtomicString& alt = fastGetAttribute(altAttr); | 272 const AtomicString& alt = fastGetAttribute(altAttr); |
264 if (!alt.isNull()) | 273 if (!alt.isNull()) |
265 return alt; | 274 return alt; |
266 // fall back to title attribute | 275 // fall back to title attribute |
267 return fastGetAttribute(titleAttr); | 276 return fastGetAttribute(titleAttr); |
268 } | 277 } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 return candidate; | 320 return candidate; |
312 } | 321 } |
313 return ImageCandidate(); | 322 return ImageCandidate(); |
314 } | 323 } |
315 | 324 |
316 RenderObject* HTMLImageElement::createRenderer(RenderStyle* style) | 325 RenderObject* HTMLImageElement::createRenderer(RenderStyle* style) |
317 { | 326 { |
318 if (style->hasContent()) | 327 if (style->hasContent()) |
319 return RenderObject::createObject(this, style); | 328 return RenderObject::createObject(this, style); |
320 | 329 |
| 330 if (m_useFallbackContent) |
| 331 return new RenderBlockFlow(this); |
| 332 |
321 RenderImage* image = new RenderImage(this); | 333 RenderImage* image = new RenderImage(this); |
322 image->setImageResource(RenderImageResource::create()); | 334 image->setImageResource(RenderImageResource::create()); |
323 image->setImageDevicePixelRatio(m_imageDevicePixelRatio); | 335 image->setImageDevicePixelRatio(m_imageDevicePixelRatio); |
324 return image; | 336 return image; |
325 } | 337 } |
326 | 338 |
327 bool HTMLImageElement::canStartSelection() const | 339 bool HTMLImageElement::canStartSelection() const |
328 { | 340 { |
329 if (shadow()) | 341 if (shadow()) |
330 return HTMLElement::canStartSelection(); | 342 return HTMLElement::canStartSelection(); |
331 | 343 |
332 return false; | 344 return false; |
333 } | 345 } |
334 | 346 |
335 void HTMLImageElement::attach(const AttachContext& context) | 347 void HTMLImageElement::attach(const AttachContext& context) |
336 { | 348 { |
337 HTMLElement::attach(context); | 349 HTMLElement::attach(context); |
338 | 350 |
339 if (renderer() && renderer()->isImage()) { | 351 if (renderer() && renderer()->isImage()) { |
340 RenderImage* renderImage = toRenderImage(renderer()); | 352 RenderImage* renderImage = toRenderImage(renderer()); |
341 RenderImageResource* renderImageResource = renderImage->imageResource(); | 353 RenderImageResource* renderImageResource = renderImage->imageResource(); |
342 if (renderImageResource->hasImage()) | 354 if (renderImageResource->hasImage()) |
343 return; | 355 return; |
344 | 356 |
345 // If we have no image at all because we have no src attribute, set | |
346 // image height and width for the alt text instead. | |
347 if (!imageLoader().image() && !renderImageResource->cachedImage()) | 357 if (!imageLoader().image() && !renderImageResource->cachedImage()) |
348 renderImage->setImageSizeForAltText(); | 358 return; |
349 else | 359 renderImageResource->setImageResource(imageLoader().image()); |
350 renderImageResource->setImageResource(imageLoader().image()); | |
351 | |
352 } | 360 } |
353 } | 361 } |
354 | 362 |
355 Node::InsertionNotificationRequest HTMLImageElement::insertedInto(ContainerNode*
insertionPoint) | 363 Node::InsertionNotificationRequest HTMLImageElement::insertedInto(ContainerNode*
insertionPoint) |
356 { | 364 { |
357 if (!m_formWasSetByParser || NodeTraversal::highestAncestorOrSelf(*insertion
Point) != NodeTraversal::highestAncestorOrSelf(*m_form.get())) | 365 if (!m_formWasSetByParser || NodeTraversal::highestAncestorOrSelf(*insertion
Point) != NodeTraversal::highestAncestorOrSelf(*m_form.get())) |
358 resetFormOwner(); | 366 resetFormOwner(); |
359 if (m_listener) | 367 if (m_listener) |
360 document().mediaQueryMatcher().addViewportListener(m_listener); | 368 document().mediaQueryMatcher().addViewportListener(m_listener); |
361 | 369 |
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
641 m_effectiveSizeViewportDependant = parser.viewportDependant(); | 649 m_effectiveSizeViewportDependant = parser.viewportDependant(); |
642 } | 650 } |
643 ImageCandidate candidate = bestFitSourceForImageAttributes(document().de
vicePixelRatio(), effectiveSize, fastGetAttribute(srcAttr), fastGetAttribute(src
setAttr)); | 651 ImageCandidate candidate = bestFitSourceForImageAttributes(document().de
vicePixelRatio(), effectiveSize, fastGetAttribute(srcAttr), fastGetAttribute(src
setAttr)); |
644 setBestFitURLAndDPRFromImageCandidate(candidate); | 652 setBestFitURLAndDPRFromImageCandidate(candidate); |
645 } | 653 } |
646 if (m_intrinsicSizingViewportDependant && m_effectiveSizeViewportDependant &
& !m_listener) { | 654 if (m_intrinsicSizingViewportDependant && m_effectiveSizeViewportDependant &
& !m_listener) { |
647 m_listener = ViewportChangeListener::create(this); | 655 m_listener = ViewportChangeListener::create(this); |
648 document().mediaQueryMatcher().addViewportListener(m_listener); | 656 document().mediaQueryMatcher().addViewportListener(m_listener); |
649 } | 657 } |
650 imageLoader().updateFromElement(behavior); | 658 imageLoader().updateFromElement(behavior); |
| 659 |
| 660 if (imageLoader().image() || (imageLoader().hasPendingActivity() && !imageSo
urceURL().isEmpty())) |
| 661 ensurePrimaryContent(); |
| 662 else |
| 663 ensureFallbackContent(); |
651 } | 664 } |
652 | 665 |
653 const KURL& HTMLImageElement::sourceURL() const | 666 const KURL& HTMLImageElement::sourceURL() const |
654 { | 667 { |
655 return cachedImage()->response().url(); | 668 return cachedImage()->response().url(); |
656 } | 669 } |
657 | 670 |
| 671 void HTMLImageElement::didAddUserAgentShadowRoot(ShadowRoot&) |
| 672 { |
| 673 m_altTextNode = createAltTextShadowTree(*this); |
658 } | 674 } |
| 675 |
| 676 void HTMLImageElement::ensureFallbackContent() |
| 677 { |
| 678 if (m_useFallbackContent || m_isFallbackImage) |
| 679 return; |
| 680 setUseFallbackContent(); |
| 681 reattachFallbackContent(); |
| 682 } |
| 683 |
| 684 void HTMLImageElement::ensurePrimaryContent() |
| 685 { |
| 686 if (!m_useFallbackContent) |
| 687 return; |
| 688 m_useFallbackContent = false; |
| 689 reattachFallbackContent(); |
| 690 } |
| 691 |
| 692 void HTMLImageElement::reattachFallbackContent() |
| 693 { |
| 694 // This can happen inside of attach() in the middle of a recalcStyle so we n
eed to |
| 695 // reattach synchronously here. |
| 696 if (document().inStyleRecalc()) |
| 697 reattach(); |
| 698 else |
| 699 lazyReattachIfAttached(); |
| 700 } |
| 701 |
| 702 PassRefPtr<RenderStyle> HTMLImageElement::customStyleForRenderer() |
| 703 { |
| 704 RefPtr<RenderStyle> newStyle = originalStyleForRenderer(); |
| 705 |
| 706 if (!m_useFallbackContent) |
| 707 return newStyle; |
| 708 return customStyleForAltText(*this, newStyle); |
| 709 } |
| 710 } |
OLD | NEW |