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