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