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 14 matching lines...) Expand all Loading... |
25 | 25 |
26 #include "bindings/core/v8/ScriptEventListener.h" | 26 #include "bindings/core/v8/ScriptEventListener.h" |
27 #include "core/CSSPropertyNames.h" | 27 #include "core/CSSPropertyNames.h" |
28 #include "core/HTMLNames.h" | 28 #include "core/HTMLNames.h" |
29 #include "core/MediaTypeNames.h" | 29 #include "core/MediaTypeNames.h" |
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/dom/shadow/ShadowRoot.h" |
35 #include "core/fetch/ImageResource.h" | 36 #include "core/fetch/ImageResource.h" |
36 #include "core/frame/UseCounter.h" | 37 #include "core/frame/UseCounter.h" |
37 #include "core/html/HTMLAnchorElement.h" | 38 #include "core/html/HTMLAnchorElement.h" |
38 #include "core/html/HTMLCanvasElement.h" | 39 #include "core/html/HTMLCanvasElement.h" |
39 #include "core/html/HTMLFormElement.h" | 40 #include "core/html/HTMLFormElement.h" |
| 41 #include "core/html/HTMLImageFallbackHelper.h" |
40 #include "core/html/HTMLSourceElement.h" | 42 #include "core/html/HTMLSourceElement.h" |
41 #include "core/html/canvas/CanvasRenderingContext.h" | 43 #include "core/html/canvas/CanvasRenderingContext.h" |
42 #include "core/html/parser/HTMLParserIdioms.h" | 44 #include "core/html/parser/HTMLParserIdioms.h" |
43 #include "core/html/parser/HTMLSrcsetParser.h" | 45 #include "core/html/parser/HTMLSrcsetParser.h" |
44 #include "core/inspector/ConsoleMessage.h" | 46 #include "core/inspector/ConsoleMessage.h" |
| 47 #include "core/rendering/RenderBlockFlow.h" |
45 #include "core/rendering/RenderImage.h" | 48 #include "core/rendering/RenderImage.h" |
46 #include "platform/ContentType.h" | 49 #include "platform/ContentType.h" |
47 #include "platform/MIMETypeRegistry.h" | 50 #include "platform/MIMETypeRegistry.h" |
48 #include "platform/RuntimeEnabledFeatures.h" | 51 #include "platform/RuntimeEnabledFeatures.h" |
49 | 52 |
50 namespace blink { | 53 namespace blink { |
51 | 54 |
52 using namespace HTMLNames; | 55 using namespace HTMLNames; |
53 | 56 |
54 class HTMLImageElement::ViewportChangeListener final : public MediaQueryListList
ener { | 57 class HTMLImageElement::ViewportChangeListener final : public MediaQueryListList
ener { |
(...skipping 22 matching lines...) Expand all Loading... |
77 RawPtrWillBeMember<HTMLImageElement> m_element; | 80 RawPtrWillBeMember<HTMLImageElement> m_element; |
78 }; | 81 }; |
79 | 82 |
80 HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form, bo
ol createdByParser) | 83 HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form, bo
ol createdByParser) |
81 : HTMLElement(imgTag, document) | 84 : HTMLElement(imgTag, document) |
82 , m_imageLoader(HTMLImageLoader::create(this)) | 85 , m_imageLoader(HTMLImageLoader::create(this)) |
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) |
| 90 , m_useFallbackContent(false) |
| 91 , m_isFallbackImage(false) |
87 { | 92 { |
| 93 setHasCustomStyleCallbacks(); |
88 if (form && form->inDocument()) { | 94 if (form && form->inDocument()) { |
89 #if ENABLE(OILPAN) | 95 #if ENABLE(OILPAN) |
90 m_form = form; | 96 m_form = form; |
91 #else | 97 #else |
92 m_form = form->createWeakPtr(); | 98 m_form = form->createWeakPtr(); |
93 #endif | 99 #endif |
94 m_formWasSetByParser = true; | 100 m_formWasSetByParser = true; |
95 m_form->associate(*this); | 101 m_form->associate(*this); |
96 m_form->didAssociateByParser(); | 102 m_form->didAssociateByParser(); |
97 } | 103 } |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 UseCounter::count(document(), UseCounter::SrcsetWDescriptor); | 234 UseCounter::count(document(), UseCounter::SrcsetWDescriptor); |
229 } else if (!candidate.srcOrigin()) { | 235 } else if (!candidate.srcOrigin()) { |
230 UseCounter::count(document(), UseCounter::SrcsetXDescriptor); | 236 UseCounter::count(document(), UseCounter::SrcsetXDescriptor); |
231 } | 237 } |
232 if (renderer() && renderer()->isImage()) | 238 if (renderer() && renderer()->isImage()) |
233 toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePixelRa
tio); | 239 toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePixelRa
tio); |
234 } | 240 } |
235 | 241 |
236 void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) | 242 void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) |
237 { | 243 { |
238 if (name == altAttr) { | 244 if (name == altAttr || name == titleAttr) { |
239 if (renderer() && renderer()->isImage()) | 245 if (userAgentShadowRoot()) { |
240 toRenderImage(renderer())->updateAltText(); | 246 Element* text = userAgentShadowRoot()->getElementById("alttext"); |
| 247 String value = altText(); |
| 248 if (text && text->textContent() != value) |
| 249 text->setTextContent(altText()); |
| 250 } |
241 } else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) { | 251 } else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) { |
242 selectSourceURL(ImageLoader::UpdateIgnorePreviousError); | 252 selectSourceURL(ImageLoader::UpdateIgnorePreviousError); |
243 } else if (name == usemapAttr) { | 253 } else if (name == usemapAttr) { |
244 setIsLink(!value.isNull()); | 254 setIsLink(!value.isNull()); |
245 } else { | 255 } else { |
246 HTMLElement::parseAttribute(name, value); | 256 HTMLElement::parseAttribute(name, value); |
247 } | 257 } |
248 } | 258 } |
249 | 259 |
250 const AtomicString& HTMLImageElement::altText() const | 260 String HTMLImageElement::altText() const |
251 { | 261 { |
252 // lets figure out the alt text.. magic stuff | 262 // lets figure out the alt text.. magic stuff |
253 // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen | 263 // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen |
254 // also heavily discussed by Hixie on bugzilla | 264 // also heavily discussed by Hixie on bugzilla |
255 const AtomicString& alt = fastGetAttribute(altAttr); | 265 const AtomicString& alt = fastGetAttribute(altAttr); |
256 if (!alt.isNull()) | 266 if (!alt.isNull()) |
257 return alt; | 267 return alt; |
258 // fall back to title attribute | 268 // fall back to title attribute |
259 return fastGetAttribute(titleAttr); | 269 return fastGetAttribute(titleAttr); |
260 } | 270 } |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
306 return candidate; | 316 return candidate; |
307 } | 317 } |
308 return ImageCandidate(); | 318 return ImageCandidate(); |
309 } | 319 } |
310 | 320 |
311 RenderObject* HTMLImageElement::createRenderer(RenderStyle* style) | 321 RenderObject* HTMLImageElement::createRenderer(RenderStyle* style) |
312 { | 322 { |
313 if (style->hasContent()) | 323 if (style->hasContent()) |
314 return RenderObject::createObject(this, style); | 324 return RenderObject::createObject(this, style); |
315 | 325 |
| 326 if (m_useFallbackContent) |
| 327 return new RenderBlockFlow(this); |
| 328 |
316 RenderImage* image = new RenderImage(this); | 329 RenderImage* image = new RenderImage(this); |
317 image->setImageResource(RenderImageResource::create()); | 330 image->setImageResource(RenderImageResource::create()); |
318 image->setImageDevicePixelRatio(m_imageDevicePixelRatio); | 331 image->setImageDevicePixelRatio(m_imageDevicePixelRatio); |
319 return image; | 332 return image; |
320 } | 333 } |
321 | 334 |
322 bool HTMLImageElement::canStartSelection() const | 335 bool HTMLImageElement::canStartSelection() const |
323 { | 336 { |
324 if (shadow()) | 337 if (shadow()) |
325 return HTMLElement::canStartSelection(); | 338 return HTMLElement::canStartSelection(); |
326 | 339 |
327 return false; | 340 return false; |
328 } | 341 } |
329 | 342 |
330 void HTMLImageElement::attach(const AttachContext& context) | 343 void HTMLImageElement::attach(const AttachContext& context) |
331 { | 344 { |
332 HTMLElement::attach(context); | 345 HTMLElement::attach(context); |
333 | 346 |
334 if (renderer() && renderer()->isImage()) { | 347 if (renderer() && renderer()->isImage()) { |
335 RenderImage* renderImage = toRenderImage(renderer()); | 348 RenderImage* renderImage = toRenderImage(renderer()); |
336 RenderImageResource* renderImageResource = renderImage->imageResource(); | 349 RenderImageResource* renderImageResource = renderImage->imageResource(); |
337 if (renderImageResource->hasImage()) | 350 if (renderImageResource->hasImage()) |
338 return; | 351 return; |
339 | 352 |
340 // If we have no image at all because we have no src attribute, set | |
341 // image height and width for the alt text instead. | |
342 if (!imageLoader().image() && !renderImageResource->cachedImage()) | 353 if (!imageLoader().image() && !renderImageResource->cachedImage()) |
343 renderImage->setImageSizeForAltText(); | 354 return; |
344 else | 355 renderImageResource->setImageResource(imageLoader().image()); |
345 renderImageResource->setImageResource(imageLoader().image()); | |
346 | |
347 } | 356 } |
348 } | 357 } |
349 | 358 |
350 Node::InsertionNotificationRequest HTMLImageElement::insertedInto(ContainerNode*
insertionPoint) | 359 Node::InsertionNotificationRequest HTMLImageElement::insertedInto(ContainerNode*
insertionPoint) |
351 { | 360 { |
352 if (!m_formWasSetByParser || NodeTraversal::highestAncestorOrSelf(*insertion
Point) != NodeTraversal::highestAncestorOrSelf(*m_form.get())) | 361 if (!m_formWasSetByParser || NodeTraversal::highestAncestorOrSelf(*insertion
Point) != NodeTraversal::highestAncestorOrSelf(*m_form.get())) |
353 resetFormOwner(); | 362 resetFormOwner(); |
354 if (m_listener) | 363 if (m_listener) |
355 document().mediaQueryMatcher().addViewportListener(m_listener); | 364 document().mediaQueryMatcher().addViewportListener(m_listener); |
356 | 365 |
357 bool imageWasModified = false; | 366 bool imageWasModified = false; |
358 if (RuntimeEnabledFeatures::pictureEnabled() && document().isActive()) { | 367 if (RuntimeEnabledFeatures::pictureEnabled() && document().isActive()) { |
359 ImageCandidate candidate = findBestFitImageFromPictureParent(); | 368 ImageCandidate candidate = findBestFitImageFromPictureParent(); |
360 if (!candidate.isEmpty()) { | 369 if (!candidate.isEmpty()) { |
361 setBestFitURLAndDPRFromImageCandidate(candidate); | 370 setBestFitURLAndDPRFromImageCandidate(candidate); |
362 imageWasModified = true; | 371 imageWasModified = true; |
363 } | 372 } |
364 } | 373 } |
365 | 374 |
366 // If we have been inserted from a renderer-less document, | 375 // If we have been inserted from a renderer-less document, |
367 // our loader may have not fetched the image, so do it now. | 376 // our loader may have not fetched the image, so do it now. |
368 if ((insertionPoint->inDocument() && !imageLoader().image()) || imageWasModi
fied) | 377 if ((insertionPoint->inDocument() && !imageLoader().image()) || imageWasModi
fied) |
369 imageLoader().updateFromElement(ImageLoader::UpdateNormal, m_elementCrea
tedByParser ? ImageLoader::ForceLoadImmediately : ImageLoader::LoadNormally); | 378 imageLoader().updateFromElement(ImageLoader::UpdateNormal); |
370 | 379 |
371 return HTMLElement::insertedInto(insertionPoint); | 380 return HTMLElement::insertedInto(insertionPoint); |
372 } | 381 } |
373 | 382 |
374 void HTMLImageElement::removedFrom(ContainerNode* insertionPoint) | 383 void HTMLImageElement::removedFrom(ContainerNode* insertionPoint) |
375 { | 384 { |
376 if (!m_form || NodeTraversal::highestAncestorOrSelf(*m_form.get()) != NodeTr
aversal::highestAncestorOrSelf(*this)) | 385 if (!m_form || NodeTraversal::highestAncestorOrSelf(*m_form.get()) != NodeTr
aversal::highestAncestorOrSelf(*this)) |
377 resetFormOwner(); | 386 resetFormOwner(); |
378 if (m_listener) | 387 if (m_listener) |
379 document().mediaQueryMatcher().removeViewportListener(m_listener); | 388 document().mediaQueryMatcher().removeViewportListener(m_listener); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
638 effectiveSize = parser.length(); | 647 effectiveSize = parser.length(); |
639 } | 648 } |
640 ImageCandidate candidate = bestFitSourceForImageAttributes(document().de
vicePixelRatio(), effectiveSize, fastGetAttribute(srcAttr), fastGetAttribute(src
setAttr), &document()); | 649 ImageCandidate candidate = bestFitSourceForImageAttributes(document().de
vicePixelRatio(), effectiveSize, fastGetAttribute(srcAttr), fastGetAttribute(src
setAttr), &document()); |
641 setBestFitURLAndDPRFromImageCandidate(candidate); | 650 setBestFitURLAndDPRFromImageCandidate(candidate); |
642 } | 651 } |
643 if (m_intrinsicSizingViewportDependant && !m_listener) { | 652 if (m_intrinsicSizingViewportDependant && !m_listener) { |
644 m_listener = ViewportChangeListener::create(this); | 653 m_listener = ViewportChangeListener::create(this); |
645 document().mediaQueryMatcher().addViewportListener(m_listener); | 654 document().mediaQueryMatcher().addViewportListener(m_listener); |
646 } | 655 } |
647 imageLoader().updateFromElement(behavior); | 656 imageLoader().updateFromElement(behavior); |
| 657 |
| 658 if (imageLoader().image() || (imageLoader().hasPendingActivity() && !imageSo
urceURL().isEmpty())) |
| 659 ensurePrimaryContent(); |
| 660 else |
| 661 ensureFallbackContent(); |
648 } | 662 } |
649 | 663 |
650 const KURL& HTMLImageElement::sourceURL() const | 664 const KURL& HTMLImageElement::sourceURL() const |
651 { | 665 { |
652 return cachedImage()->response().url(); | 666 return cachedImage()->response().url(); |
653 } | 667 } |
654 | 668 |
| 669 void HTMLImageElement::didAddUserAgentShadowRoot(ShadowRoot&) |
| 670 { |
| 671 HTMLImageFallbackHelper::createAltTextShadowTree(*this); |
655 } | 672 } |
| 673 |
| 674 void HTMLImageElement::ensureFallbackContent() |
| 675 { |
| 676 if (m_useFallbackContent || m_isFallbackImage) |
| 677 return; |
| 678 setUseFallbackContent(); |
| 679 reattachFallbackContent(); |
| 680 } |
| 681 |
| 682 void HTMLImageElement::ensurePrimaryContent() |
| 683 { |
| 684 if (!m_useFallbackContent) |
| 685 return; |
| 686 m_useFallbackContent = false; |
| 687 reattachFallbackContent(); |
| 688 } |
| 689 |
| 690 void HTMLImageElement::reattachFallbackContent() |
| 691 { |
| 692 // This can happen inside of attach() in the middle of a recalcStyle so we n
eed to |
| 693 // reattach synchronously here. |
| 694 if (document().inStyleRecalc()) |
| 695 reattach(); |
| 696 else |
| 697 lazyReattachIfAttached(); |
| 698 } |
| 699 |
| 700 PassRefPtr<RenderStyle> HTMLImageElement::customStyleForRenderer() |
| 701 { |
| 702 RefPtr<RenderStyle> newStyle = originalStyleForRenderer(); |
| 703 |
| 704 if (!m_useFallbackContent) |
| 705 return newStyle; |
| 706 return HTMLImageFallbackHelper::customStyleForAltText(*this, newStyle); |
| 707 } |
| 708 |
| 709 void HTMLImageElement::setUseFallbackContent() |
| 710 { |
| 711 m_useFallbackContent = true; |
| 712 if (document().inStyleRecalc()) |
| 713 return; |
| 714 ensureUserAgentShadowRoot(); |
| 715 } |
| 716 } |
OLD | NEW |