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

Side by Side Diff: Source/core/rendering/RenderImage.cpp

Issue 923953002: Move rendering/RenderImage* to layout/LayoutImage* (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Created 5 years, 10 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
« no previous file with comments | « Source/core/rendering/RenderImage.h ('k') | Source/core/rendering/RenderImageResource.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 /*
2 * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
3 * (C) 1999 Antti Koivisto (koivisto@kde.org)
4 * (C) 2000 Dirk Mueller (mueller@kde.org)
5 * (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com)
6 * (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
7 * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011 Apple Inc. All r ights reserved.
8 * Copyright (C) 2010 Google Inc. All rights reserved.
9 * Copyright (C) Research In Motion Limited 2011-2012. All rights reserved.
10 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU Library General Public License
22 * along with this library; see the file COPYING.LIB. If not, write to
23 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301, USA.
25 *
26 */
27
28 #include "config.h"
29 #include "core/rendering/RenderImage.h"
30
31 #include "core/HTMLNames.h"
32 #include "core/editing/FrameSelection.h"
33 #include "core/fetch/ImageResource.h"
34 #include "core/fetch/ResourceLoadPriorityOptimizer.h"
35 #include "core/fetch/ResourceLoader.h"
36 #include "core/frame/LocalFrame.h"
37 #include "core/html/HTMLAreaElement.h"
38 #include "core/html/HTMLImageElement.h"
39 #include "core/html/HTMLInputElement.h"
40 #include "core/html/HTMLMapElement.h"
41 #include "core/layout/HitTestResult.h"
42 #include "core/layout/Layer.h"
43 #include "core/layout/PaintInfo.h"
44 #include "core/layout/TextRunConstructor.h"
45 #include "core/page/Page.h"
46 #include "core/paint/ImagePainter.h"
47 #include "core/rendering/RenderView.h"
48 #include "core/svg/graphics/SVGImage.h"
49 #include "platform/fonts/Font.h"
50 #include "platform/fonts/FontCache.h"
51
52 namespace blink {
53
54 using namespace HTMLNames;
55
56 RenderImage::RenderImage(Element* element)
57 : RenderReplaced(element, LayoutSize())
58 , m_didIncrementVisuallyNonEmptyPixelCount(false)
59 , m_isGeneratedContent(false)
60 , m_imageDevicePixelRatio(1.0f)
61 {
62 ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->addLayoutObj ect(this);
63 }
64
65 RenderImage* RenderImage::createAnonymous(Document* document)
66 {
67 RenderImage* image = new RenderImage(0);
68 image->setDocumentForAnonymous(document);
69 return image;
70 }
71
72 RenderImage::~RenderImage()
73 {
74 }
75
76 void RenderImage::destroy()
77 {
78 ASSERT(m_imageResource);
79 m_imageResource->shutdown();
80 RenderReplaced::destroy();
81 }
82
83 void RenderImage::setImageResource(PassOwnPtr<RenderImageResource> imageResource )
84 {
85 ASSERT(!m_imageResource);
86 m_imageResource = imageResource;
87 m_imageResource->initialize(this);
88 }
89
90 void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
91 {
92 if (documentBeingDestroyed())
93 return;
94
95 if (hasBoxDecorationBackground() || hasMask() || hasShapeOutside())
96 RenderReplaced::imageChanged(newImage, rect);
97
98 if (!m_imageResource)
99 return;
100
101 if (newImage != m_imageResource->imagePtr())
102 return;
103
104 // Per the spec, we let the server-sent header override srcset/other sources of dpr.
105 // https://github.com/igrigorik/http-client-hints/blob/master/draft-grigorik -http-client-hints-01.txt#L255
106 if (m_imageResource->cachedImage() && m_imageResource->cachedImage()->hasDev icePixelRatioHeaderValue())
107 m_imageDevicePixelRatio = 1 / m_imageResource->cachedImage()->devicePixe lRatioHeaderValue();
108
109 if (!m_didIncrementVisuallyNonEmptyPixelCount) {
110 // At a zoom level of 1 the image is guaranteed to have an integer size.
111 view()->frameView()->incrementVisuallyNonEmptyPixelCount(flooredIntSize( m_imageResource->imageSize(1.0f)));
112 m_didIncrementVisuallyNonEmptyPixelCount = true;
113 }
114
115 repaintOrMarkForLayout(rect);
116 }
117
118 void RenderImage::updateIntrinsicSizeIfNeeded(const LayoutSize& newSize)
119 {
120 if (m_imageResource->errorOccurred() || !m_imageResource->hasImage())
121 return;
122 setIntrinsicSize(newSize);
123 }
124
125 void RenderImage::updateInnerContentRect()
126 {
127 // Propagate container size to the image resource.
128 LayoutRect containerRect = replacedContentRect();
129 IntSize containerSize(containerRect.width(), containerRect.height());
130 if (!containerSize.isEmpty())
131 m_imageResource->setContainerSizeForRenderer(containerSize);
132 }
133
134 void RenderImage::repaintOrMarkForLayout(const IntRect* rect)
135 {
136 LayoutSize oldIntrinsicSize = intrinsicSize();
137 LayoutSize newIntrinsicSize = m_imageResource->intrinsicSize(style()->effect iveZoom());
138 updateIntrinsicSizeIfNeeded(newIntrinsicSize);
139
140 // In the case of generated image content using :before/:after/content, we m ight not be
141 // in the render tree yet. In that case, we just need to update our intrinsi c size.
142 // layout() will be called after we are inserted in the tree which will take care of
143 // what we are doing here.
144 if (!containingBlock())
145 return;
146
147 bool imageSourceHasChangedSize = oldIntrinsicSize != newIntrinsicSize;
148 if (imageSourceHasChangedSize)
149 setPreferredLogicalWidthsDirty();
150
151 // If the actual area occupied by the image has changed and it is not constr ained by style then a layout is required.
152 bool imageSizeIsConstrained = style()->logicalWidth().isSpecified() && style ()->logicalHeight().isSpecified();
153
154 // FIXME: We only need to recompute the containing block's preferred size if the containing block's size
155 // depends on the image's size (i.e., the container uses shrink-to-fit sizin g).
156 // There's no easy way to detect that shrink-to-fit is needed, always force a layout.
157 bool containingBlockNeedsToRecomputePreferredSize = style()->logicalWidth(). isPercent() || style()->logicalMaxWidth().isPercent() || style()->logicalMinWid th().isPercent();
158
159 if (imageSourceHasChangedSize && (!imageSizeIsConstrained || containingBlock NeedsToRecomputePreferredSize)) {
160 setNeedsLayoutAndFullPaintInvalidation();
161 return;
162 }
163
164 // The image hasn't changed in size or its style constrains its size, so a p aint invalidation will suffice.
165 if (everHadLayout() && !selfNeedsLayout()) {
166 // The inner content rectangle is calculated during layout, but may need an update now
167 // (unless the box has already been scheduled for layout). In order to c alculate it, we
168 // may need values from the containing block, though, so make sure that we're not too
169 // early. It may be that layout hasn't even taken place once yet.
170 updateInnerContentRect();
171 }
172
173 LayoutRect paintInvalidationRect;
174 if (rect) {
175 // The image changed rect is in source image coordinates (without zoom),
176 // so map from the bounds of the image to the contentsBox.
177 const FloatSize imageSizeWithoutZoom(m_imageResource->imageSize(1 / styl e()->effectiveZoom()));
178 paintInvalidationRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatP oint(), imageSizeWithoutZoom), contentBoxRect()));
179 // Guard against too-large changed rects.
180 paintInvalidationRect.intersect(contentBoxRect());
181 } else {
182 paintInvalidationRect = contentBoxRect();
183 }
184
185 {
186 DisableCompositingQueryAsserts disabler;
187 // FIXME: We should not allow paint invalidation out of paint invalidati on state. crbug.com/457415
188 DisablePaintInvalidationStateAsserts paintInvalidationAssertDisabler;
189 invalidatePaintRectangle(paintInvalidationRect);
190 }
191
192 // Tell any potential compositing layers that the image needs updating.
193 contentChanged(ImageChanged);
194 }
195
196 void RenderImage::notifyFinished(Resource* newImage)
197 {
198 if (!m_imageResource)
199 return;
200
201 if (documentBeingDestroyed())
202 return;
203
204 invalidateBackgroundObscurationStatus();
205
206 if (newImage == m_imageResource->cachedImage()) {
207 // tell any potential compositing layers
208 // that the image is done and they can reference it directly.
209 contentChanged(ImageChanged);
210 }
211 }
212
213 void RenderImage::paintReplaced(const PaintInfo& paintInfo, const LayoutPoint& p aintOffset)
214 {
215 ImagePainter(*this).paintReplaced(paintInfo, paintOffset);
216 }
217
218 void RenderImage::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffs et)
219 {
220 ImagePainter(*this).paint(paintInfo, paintOffset);
221 }
222
223 void RenderImage::areaElementFocusChanged(HTMLAreaElement* areaElement)
224 {
225 ASSERT(areaElement->imageElement() == node());
226
227 Path path = areaElement->computePath(this);
228 if (path.isEmpty())
229 return;
230
231 const LayoutStyle* areaElementStyle = areaElement->computedStyle();
232 unsigned short outlineWidth = areaElementStyle->outlineWidth();
233
234 IntRect paintInvalidationRect = enclosingIntRect(path.boundingRect());
235 paintInvalidationRect.moveBy(-IntPoint(absoluteContentBoxOffset()));
236 paintInvalidationRect.inflate(outlineWidth);
237
238 repaintOrMarkForLayout(&paintInvalidationRect);
239 }
240
241 bool RenderImage::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox*) const
242 {
243 if (!RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(bleedAvoidan ce))
244 return false;
245
246 return !const_cast<RenderImage*>(this)->boxDecorationBackgroundIsKnownToBeOb scured();
247 }
248
249 bool RenderImage::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned) const
250 {
251 if (!m_imageResource->hasImage() || m_imageResource->errorOccurred())
252 return false;
253 if (m_imageResource->cachedImage() && !m_imageResource->cachedImage()->isLoa ded())
254 return false;
255 if (!contentBoxRect().contains(localRect))
256 return false;
257 EFillBox backgroundClip = style()->backgroundClip();
258 // Background paints under borders.
259 if (backgroundClip == BorderFillBox && style()->hasBorder() && !style()->bor derObscuresBackground())
260 return false;
261 // Background shows in padding area.
262 if ((backgroundClip == BorderFillBox || backgroundClip == PaddingFillBox) && style()->hasPadding())
263 return false;
264 // Object-position may leave parts of the content box empty, regardless of t he value of object-fit.
265 if (style()->objectPosition() != LayoutStyle::initialObjectPosition())
266 return false;
267 // Object-fit may leave parts of the content box empty.
268 ObjectFit objectFit = style()->objectFit();
269 if (objectFit != ObjectFitFill && objectFit != ObjectFitCover)
270 return false;
271 // Check for image with alpha.
272 return m_imageResource->cachedImage() && m_imageResource->cachedImage()->cur rentFrameKnownToBeOpaque(this);
273 }
274
275 bool RenderImage::computeBackgroundIsKnownToBeObscured()
276 {
277 if (!hasBackground())
278 return false;
279
280 LayoutRect paintedExtent;
281 if (!getBackgroundPaintedExtent(paintedExtent))
282 return false;
283 return foregroundIsKnownToBeOpaqueInRect(paintedExtent, 0);
284 }
285
286 LayoutUnit RenderImage::minimumReplacedHeight() const
287 {
288 return m_imageResource->errorOccurred() ? intrinsicSize().height() : LayoutU nit();
289 }
290
291 HTMLMapElement* RenderImage::imageMap() const
292 {
293 HTMLImageElement* i = isHTMLImageElement(node()) ? toHTMLImageElement(node() ) : 0;
294 return i ? i->treeScope().getImageMap(i->fastGetAttribute(usemapAttr)) : 0;
295 }
296
297 bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& resu lt, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOf fset, HitTestAction hitTestAction)
298 {
299 HitTestResult tempResult(result.hitTestLocation());
300 bool inside = RenderReplaced::nodeAtPoint(request, tempResult, locationInCon tainer, accumulatedOffset, hitTestAction);
301
302 if (tempResult.innerNode() && node()) {
303 if (HTMLMapElement* map = imageMap()) {
304 LayoutRect contentBox = contentBoxRect();
305 float scaleFactor = 1 / style()->effectiveZoom();
306 LayoutPoint mapLocation = locationInContainer.point() - toLayoutSize (accumulatedOffset) - locationOffset() - toLayoutSize(contentBox.location());
307 mapLocation.scale(scaleFactor, scaleFactor);
308
309 if (map->mapMouseEvent(mapLocation, contentBox.size(), tempResult))
310 tempResult.setInnerNonSharedNode(node());
311 }
312 }
313
314 if (!inside && result.isRectBasedTest())
315 result.append(tempResult);
316 if (inside)
317 result = tempResult;
318 return inside;
319 }
320
321 void RenderImage::layout()
322 {
323 RenderReplaced::layout();
324 updateInnerContentRect();
325 }
326
327 bool RenderImage::updateImageLoadingPriorities()
328 {
329 if (!m_imageResource || !m_imageResource->cachedImage() || m_imageResource-> cachedImage()->isLoaded())
330 return false;
331
332 LayoutRect viewBounds = viewRect();
333 LayoutRect objectBounds = absoluteContentBox();
334
335 // The object bounds might be empty right now, so intersects will fail since it doesn't deal
336 // with empty rects. Use LayoutRect::contains in that case.
337 bool isVisible;
338 if (!objectBounds.isEmpty())
339 isVisible = viewBounds.intersects(objectBounds);
340 else
341 isVisible = viewBounds.contains(objectBounds);
342
343 ResourceLoadPriorityOptimizer::VisibilityStatus status = isVisible ?
344 ResourceLoadPriorityOptimizer::Visible : ResourceLoadPriorityOptimizer:: NotVisible;
345
346 LayoutRect screenArea;
347 if (!objectBounds.isEmpty()) {
348 screenArea = viewBounds;
349 screenArea.intersect(objectBounds);
350 }
351
352 ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->notifyImageR esourceVisibility(m_imageResource->cachedImage(), status, screenArea);
353
354 return true;
355 }
356
357 void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, dou ble& intrinsicRatio) const
358 {
359 RenderReplaced::computeIntrinsicRatioInformation(intrinsicSize, intrinsicRat io);
360
361 // Our intrinsicSize is empty if we're rendering generated images with relat ive width/height. Figure out the right intrinsic size to use.
362 if (intrinsicSize.isEmpty() && (m_imageResource->imageHasRelativeWidth() || m_imageResource->imageHasRelativeHeight())) {
363 LayoutObject* containingBlock = isOutOfFlowPositioned() ? container() : this->containingBlock();
364 if (containingBlock->isBox()) {
365 RenderBox* box = toRenderBox(containingBlock);
366 intrinsicSize.setWidth(box->availableLogicalWidth().toFloat());
367 intrinsicSize.setHeight(box->availableLogicalHeight(IncludeMarginBor derPadding).toFloat());
368 }
369 }
370 // Don't compute an intrinsic ratio to preserve historical WebKit behavior i f we're painting alt text and/or a broken image.
371 // Video is excluded from this behavior because video elements have a defaul t aspect ratio that a failed poster image load should not override.
372 if (m_imageResource && m_imageResource->errorOccurred() && !isVideo()) {
373 intrinsicRatio = 1;
374 return;
375 }
376 }
377
378 bool RenderImage::needsPreferredWidthsRecalculation() const
379 {
380 if (RenderReplaced::needsPreferredWidthsRecalculation())
381 return true;
382 return embeddedContentBox();
383 }
384
385 RenderBox* RenderImage::embeddedContentBox() const
386 {
387 if (!m_imageResource)
388 return 0;
389
390 ImageResource* cachedImage = m_imageResource->cachedImage();
391 if (cachedImage && cachedImage->image() && cachedImage->image()->isSVGImage( ))
392 return toSVGImage(cachedImage->image())->embeddedContentBox();
393
394 return 0;
395 }
396
397 } // namespace blink
OLDNEW
« no previous file with comments | « Source/core/rendering/RenderImage.h ('k') | Source/core/rendering/RenderImageResource.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698