| 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. |
| 11 * | 11 * |
| 12 * This library is distributed in the hope that it will be useful, | 12 * This library is distributed in the hope that it will be useful, |
| 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 15 * Library General Public License for more details. | 15 * Library General Public License for more details. |
| 16 * | 16 * |
| 17 * You should have received a copy of the GNU Library General Public License | 17 * You should have received a copy of the GNU Library General Public License |
| 18 * along with this library; see the file COPYING.LIB. If not, write to | 18 * along with this library; see the file COPYING.LIB. If not, write to |
| 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | 19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| 20 * Boston, MA 02110-1301, USA. | 20 * Boston, MA 02110-1301, USA. |
| 21 */ | 21 */ |
| 22 | 22 |
| 23 #include "config.h" | 23 #include "config.h" |
| 24 #include "core/html/HTMLImageElement.h" | 24 #include "core/html/HTMLImageElement.h" |
| 25 | 25 |
| 26 #include "CSSPropertyNames.h" | 26 #include "CSSPropertyNames.h" |
| 27 #include "HTMLNames.h" | 27 #include "HTMLNames.h" |
| 28 #include "MediaTypeNames.h" |
| 28 #include "RuntimeEnabledFeatures.h" | 29 #include "RuntimeEnabledFeatures.h" |
| 29 #include "bindings/v8/ScriptEventListener.h" | 30 #include "bindings/v8/ScriptEventListener.h" |
| 31 #include "core/css/MediaQueryMatcher.h" |
| 30 #include "core/css/MediaValuesCached.h" | 32 #include "core/css/MediaValuesCached.h" |
| 31 #include "core/css/parser/SizesAttributeParser.h" | 33 #include "core/css/parser/SizesAttributeParser.h" |
| 32 #include "core/dom/Attribute.h" | 34 #include "core/dom/Attribute.h" |
| 33 #include "core/fetch/ImageResource.h" | 35 #include "core/fetch/ImageResource.h" |
| 34 #include "core/html/HTMLAnchorElement.h" | 36 #include "core/html/HTMLAnchorElement.h" |
| 35 #include "core/html/HTMLCanvasElement.h" | 37 #include "core/html/HTMLCanvasElement.h" |
| 36 #include "core/html/HTMLFormElement.h" | 38 #include "core/html/HTMLFormElement.h" |
| 39 #include "core/html/HTMLSourceElement.h" |
| 37 #include "core/html/canvas/CanvasRenderingContext.h" | 40 #include "core/html/canvas/CanvasRenderingContext.h" |
| 38 #include "core/html/parser/HTMLParserIdioms.h" | 41 #include "core/html/parser/HTMLParserIdioms.h" |
| 39 #include "core/html/parser/HTMLSrcsetParser.h" | 42 #include "core/html/parser/HTMLSrcsetParser.h" |
| 40 #include "core/rendering/RenderImage.h" | 43 #include "core/rendering/RenderImage.h" |
| 44 #include "platform/MIMETypeRegistry.h" |
| 41 | 45 |
| 42 using namespace std; | 46 using namespace std; |
| 43 | 47 |
| 44 namespace WebCore { | 48 namespace WebCore { |
| 45 | 49 |
| 46 using namespace HTMLNames; | 50 using namespace HTMLNames; |
| 47 | 51 |
| 48 HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form) | 52 HTMLImageElement::HTMLImageElement(Document& document, HTMLFormElement* form) |
| 49 : HTMLElement(imgTag, document) | 53 : HTMLElement(imgTag, document) |
| 50 , m_imageLoader(this) | 54 , m_imageLoader(this) |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 m_form->disassociate(*this); | 147 m_form->disassociate(*this); |
| 144 } | 148 } |
| 145 if (nearestForm) { | 149 if (nearestForm) { |
| 146 m_form = nearestForm->createWeakPtr(); | 150 m_form = nearestForm->createWeakPtr(); |
| 147 m_form->associate(*this); | 151 m_form->associate(*this); |
| 148 } else { | 152 } else { |
| 149 m_form = WeakPtr<HTMLFormElement>(); | 153 m_form = WeakPtr<HTMLFormElement>(); |
| 150 } | 154 } |
| 151 } | 155 } |
| 152 | 156 |
| 157 void HTMLImageElement::setBestFitURLAndDPRFromImageCandidate(const ImageCandidat
e& candidate) |
| 158 { |
| 159 m_bestFitImageURL = candidate.url(); |
| 160 float candidateScaleFactor = candidate.scaleFactor(); |
| 161 // FIXME: Make this ">0" part match the spec, once it settles. |
| 162 if (candidateScaleFactor > 0) |
| 163 m_imageDevicePixelRatio = 1 / candidateScaleFactor; |
| 164 if (renderer() && renderer()->isImage()) |
| 165 toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePixelRa
tio); |
| 166 } |
| 167 |
| 153 void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) | 168 void HTMLImageElement::parseAttribute(const QualifiedName& name, const AtomicStr
ing& value) |
| 154 { | 169 { |
| 155 if (name == altAttr) { | 170 if (name == altAttr) { |
| 156 if (renderer() && renderer()->isImage()) | 171 if (renderer() && renderer()->isImage()) |
| 157 toRenderImage(renderer())->updateAltText(); | 172 toRenderImage(renderer())->updateAltText(); |
| 158 } else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) { | 173 } else if (name == srcAttr || name == srcsetAttr || name == sizesAttr) { |
| 159 int effectiveSize = 0; | 174 unsigned effectiveSize = 0; |
| 160 if (RuntimeEnabledFeatures::pictureSizesEnabled()) | 175 if (RuntimeEnabledFeatures::pictureSizesEnabled()) |
| 161 effectiveSize = SizesAttributeParser::findEffectiveSize(fastGetAttri
bute(sizesAttr), MediaValuesCached::create(document())); | 176 effectiveSize = SizesAttributeParser::findEffectiveSize(fastGetAttri
bute(sizesAttr), MediaValuesCached::create(document())); |
| 162 ImageCandidate candidate = bestFitSourceForImageAttributes(document().de
vicePixelRatio(), effectiveSize, fastGetAttribute(srcAttr), fastGetAttribute(src
setAttr)); | 177 ImageCandidate candidate = bestFitSourceForImageAttributes(document().de
vicePixelRatio(), effectiveSize, fastGetAttribute(srcAttr), fastGetAttribute(src
setAttr)); |
| 163 m_bestFitImageURL = candidate.toAtomicString(); | 178 setBestFitURLAndDPRFromImageCandidate(candidate); |
| 164 float candidateScaleFactor = candidate.scaleFactor(); | |
| 165 // FIXME: Make this ">0" part match the spec, once it settles. | |
| 166 if (candidateScaleFactor > 0) | |
| 167 m_imageDevicePixelRatio = 1 / candidateScaleFactor; | |
| 168 if (renderer() && renderer()->isImage()) | |
| 169 toRenderImage(renderer())->setImageDevicePixelRatio(m_imageDevicePix
elRatio); | |
| 170 m_imageLoader.updateFromElementIgnoringPreviousError(); | 179 m_imageLoader.updateFromElementIgnoringPreviousError(); |
| 171 } else if (name == usemapAttr) { | 180 } else if (name == usemapAttr) { |
| 172 setIsLink(!value.isNull()); | 181 setIsLink(!value.isNull()); |
| 173 } else if (name == compositeAttr) { | 182 } else if (name == compositeAttr) { |
| 174 // FIXME: images don't support blend modes in their compositing attribut
e. | 183 // FIXME: images don't support blend modes in their compositing attribut
e. |
| 175 blink::WebBlendMode blendOp = blink::WebBlendModeNormal; | 184 blink::WebBlendMode blendOp = blink::WebBlendModeNormal; |
| 176 if (!parseCompositeAndBlendOperator(value, m_compositeOperator, blendOp)
) | 185 if (!parseCompositeAndBlendOperator(value, m_compositeOperator, blendOp)
) |
| 177 m_compositeOperator = CompositeSourceOver; | 186 m_compositeOperator = CompositeSourceOver; |
| 178 } else { | 187 } else { |
| 179 HTMLElement::parseAttribute(name, value); | 188 HTMLElement::parseAttribute(name, value); |
| 180 } | 189 } |
| 181 } | 190 } |
| 182 | 191 |
| 183 const AtomicString& HTMLImageElement::altText() const | 192 const AtomicString& HTMLImageElement::altText() const |
| 184 { | 193 { |
| 185 // lets figure out the alt text.. magic stuff | 194 // lets figure out the alt text.. magic stuff |
| 186 // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen | 195 // http://www.w3.org/TR/1998/REC-html40-19980424/appendix/notes.html#altgen |
| 187 // also heavily discussed by Hixie on bugzilla | 196 // also heavily discussed by Hixie on bugzilla |
| 188 const AtomicString& alt = fastGetAttribute(altAttr); | 197 const AtomicString& alt = fastGetAttribute(altAttr); |
| 189 if (!alt.isNull()) | 198 if (!alt.isNull()) |
| 190 return alt; | 199 return alt; |
| 191 // fall back to title attribute | 200 // fall back to title attribute |
| 192 return fastGetAttribute(titleAttr); | 201 return fastGetAttribute(titleAttr); |
| 193 } | 202 } |
| 194 | 203 |
| 204 static bool supportedImageType(const String& type) |
| 205 { |
| 206 return MIMETypeRegistry::isSupportedImageResourceMIMEType(type); |
| 207 } |
| 208 |
| 209 // http://picture.responsiveimages.org/#update-source-set |
| 210 ImageCandidate HTMLImageElement::findBestFitImageFromPictureParent() |
| 211 { |
| 212 ASSERT(isMainThread()); |
| 213 Node* parent = parentNode(); |
| 214 if (!parent || !isHTMLPictureElement(*parent)) |
| 215 return ImageCandidate(); |
| 216 for (Node* child = parent->firstChild(); child; child = child->nextSibling()
) { |
| 217 if (child == this) |
| 218 return ImageCandidate(); |
| 219 |
| 220 if (!isHTMLSourceElement(*child)) |
| 221 continue; |
| 222 |
| 223 HTMLSourceElement* source = toHTMLSourceElement(child); |
| 224 String srcset = source->fastGetAttribute(srcsetAttr); |
| 225 if (srcset.isEmpty()) |
| 226 continue; |
| 227 String type = source->fastGetAttribute(typeAttr); |
| 228 if (!type.isEmpty() && !supportedImageType(type)) |
| 229 continue; |
| 230 |
| 231 String media = source->fastGetAttribute(mediaAttr); |
| 232 if (!media.isEmpty()) { |
| 233 RefPtr<MediaQuerySet> mediaQueries = MediaQuerySet::create(media); |
| 234 if (!document().mediaQueryMatcher().evaluate(mediaQueries.get())) |
| 235 continue; |
| 236 } |
| 237 |
| 238 unsigned effectiveSize = SizesAttributeParser::findEffectiveSize(source-
>fastGetAttribute(sizesAttr), MediaValuesCached::create(document())); |
| 239 ImageCandidate candidate = bestFitSourceForSrcsetAttribute(document().de
vicePixelRatio(), effectiveSize, source->fastGetAttribute(srcsetAttr)); |
| 240 if (candidate.isEmpty()) |
| 241 continue; |
| 242 return candidate; |
| 243 } |
| 244 return ImageCandidate(); |
| 245 } |
| 246 |
| 195 RenderObject* HTMLImageElement::createRenderer(RenderStyle* style) | 247 RenderObject* HTMLImageElement::createRenderer(RenderStyle* style) |
| 196 { | 248 { |
| 197 if (style->hasContent()) | 249 if (style->hasContent()) |
| 198 return RenderObject::createObject(this, style); | 250 return RenderObject::createObject(this, style); |
| 199 | 251 |
| 200 RenderImage* image = new RenderImage(this); | 252 RenderImage* image = new RenderImage(this); |
| 201 image->setImageResource(RenderImageResource::create()); | 253 image->setImageResource(RenderImageResource::create()); |
| 202 image->setImageDevicePixelRatio(m_imageDevicePixelRatio); | 254 image->setImageDevicePixelRatio(m_imageDevicePixelRatio); |
| 203 return image; | 255 return image; |
| 204 } | 256 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 229 renderImageResource->setImageResource(m_imageLoader.image()); | 281 renderImageResource->setImageResource(m_imageLoader.image()); |
| 230 | 282 |
| 231 } | 283 } |
| 232 } | 284 } |
| 233 | 285 |
| 234 Node::InsertionNotificationRequest HTMLImageElement::insertedInto(ContainerNode*
insertionPoint) | 286 Node::InsertionNotificationRequest HTMLImageElement::insertedInto(ContainerNode*
insertionPoint) |
| 235 { | 287 { |
| 236 if (!m_formWasSetByParser || insertionPoint->highestAncestorOrSelf() != m_fo
rm->highestAncestorOrSelf()) | 288 if (!m_formWasSetByParser || insertionPoint->highestAncestorOrSelf() != m_fo
rm->highestAncestorOrSelf()) |
| 237 resetFormOwner(); | 289 resetFormOwner(); |
| 238 | 290 |
| 291 bool imageWasModified = false; |
| 292 if (RuntimeEnabledFeatures::pictureEnabled()) { |
| 293 ImageCandidate candidate = findBestFitImageFromPictureParent(); |
| 294 if (!candidate.isEmpty()) { |
| 295 setBestFitURLAndDPRFromImageCandidate(candidate); |
| 296 imageWasModified = true; |
| 297 } |
| 298 } |
| 299 |
| 239 // If we have been inserted from a renderer-less document, | 300 // If we have been inserted from a renderer-less document, |
| 240 // our loader may have not fetched the image, so do it now. | 301 // our loader may have not fetched the image, so do it now. |
| 241 if (insertionPoint->inDocument() && !m_imageLoader.image()) | 302 if ((insertionPoint->inDocument() && !m_imageLoader.image()) || imageWasModi
fied) |
| 242 m_imageLoader.updateFromElement(); | 303 m_imageLoader.updateFromElement(); |
| 243 | 304 |
| 244 return HTMLElement::insertedInto(insertionPoint); | 305 return HTMLElement::insertedInto(insertionPoint); |
| 245 } | 306 } |
| 246 | 307 |
| 247 void HTMLImageElement::removedFrom(ContainerNode* insertionPoint) | 308 void HTMLImageElement::removedFrom(ContainerNode* insertionPoint) |
| 248 { | 309 { |
| 249 if (!m_form || m_form->highestAncestorOrSelf() != highestAncestorOrSelf()) | 310 if (!m_form || m_form->highestAncestorOrSelf() != highestAncestorOrSelf()) |
| 250 resetFormOwner(); | 311 resetFormOwner(); |
| 251 HTMLElement::removedFrom(insertionPoint); | 312 HTMLElement::removedFrom(insertionPoint); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 308 int HTMLImageElement::naturalHeight() const | 369 int HTMLImageElement::naturalHeight() const |
| 309 { | 370 { |
| 310 if (!m_imageLoader.image()) | 371 if (!m_imageLoader.image()) |
| 311 return 0; | 372 return 0; |
| 312 | 373 |
| 313 return m_imageLoader.image()->imageSizeForRenderer(renderer(), 1.0f).height(
); | 374 return m_imageLoader.image()->imageSizeForRenderer(renderer(), 1.0f).height(
); |
| 314 } | 375 } |
| 315 | 376 |
| 316 const AtomicString& HTMLImageElement::currentSrc() const | 377 const AtomicString& HTMLImageElement::currentSrc() const |
| 317 { | 378 { |
| 379 // FIXME: Need to absolutize the returned value. |
| 318 return m_bestFitImageURL; | 380 return m_bestFitImageURL; |
| 319 } | 381 } |
| 320 | 382 |
| 321 bool HTMLImageElement::isURLAttribute(const Attribute& attribute) const | 383 bool HTMLImageElement::isURLAttribute(const Attribute& attribute) const |
| 322 { | 384 { |
| 323 return attribute.name() == srcAttr | 385 return attribute.name() == srcAttr |
| 324 || attribute.name() == lowsrcAttr | 386 || attribute.name() == lowsrcAttr |
| 325 || attribute.name() == longdescAttr | 387 || attribute.name() == longdescAttr |
| 326 || (attribute.name() == usemapAttr && attribute.value().string()[0] != '
#') | 388 || (attribute.name() == usemapAttr && attribute.value().string()[0] != '
#') |
| 327 || HTMLElement::isURLAttribute(attribute); | 389 || HTMLElement::isURLAttribute(attribute); |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 if (!image) | 537 if (!image) |
| 476 return FloatSize(); | 538 return FloatSize(); |
| 477 LayoutSize size; | 539 LayoutSize size; |
| 478 size = image->imageSizeForRenderer(renderer(), 1.0f); // FIXME: Not sure abo
ut this. | 540 size = image->imageSizeForRenderer(renderer(), 1.0f); // FIXME: Not sure abo
ut this. |
| 479 if (renderer() && renderer()->isRenderImage() && image->image() && !image->i
mage()->hasRelativeWidth()) | 541 if (renderer() && renderer()->isRenderImage() && image->image() && !image->i
mage()->hasRelativeWidth()) |
| 480 size.scale(toRenderImage(renderer())->imageDevicePixelRatio()); | 542 size.scale(toRenderImage(renderer())->imageDevicePixelRatio()); |
| 481 return size; | 543 return size; |
| 482 } | 544 } |
| 483 | 545 |
| 484 } | 546 } |
| OLD | NEW |