Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(272)

Side by Side Diff: Source/core/html/HTMLImageElement.cpp

Issue 481753002: Use Shadow DOM to display fallback content for images (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Updated Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698