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