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 rights reserved.
8 * Copyright (C) 2010 Google Inc. All rights reserved.
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public License
21 * along with this library; see the file COPYING.LIB. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 *
25 */
26
27 #include "config.h"
28 #include "RenderImage.h"
29
30 #include "Frame.h"
31 #include "GraphicsContext.h"
32 #include "HTMLAreaElement.h"
33 #include "HTMLImageElement.h"
34 #include "HTMLInputElement.h"
35 #include "HTMLMapElement.h"
36 #include "HTMLNames.h"
37 #include "HitTestResult.h"
38 #include "Page.h"
39 #include "RenderLayer.h"
40 #include "RenderView.h"
41 #include "SelectionController.h"
42 #include "TextRun.h"
43 #include <wtf/UnusedParam.h>
44
45 #ifdef ANDROID_LAYOUT
46 #include "Settings.h"
47 #endif
48
49 #if ENABLE(WML)
50 #include "WMLImageElement.h"
51 #include "WMLNames.h"
52 #endif
53
54 using namespace std;
55
56 namespace WebCore {
57
58 using namespace HTMLNames;
59
RenderImage(Node * node)60 RenderImage::RenderImage(Node* node)
61 : RenderReplaced(node, IntSize(0, 0))
62 , m_needsToSetSizeForAltText(false)
63 {
64 updateAltText();
65
66 view()->frameView()->setIsVisuallyNonEmpty();
67 }
68
~RenderImage()69 RenderImage::~RenderImage()
70 {
71 ASSERT(m_imageResource);
72 m_imageResource->shutdown();
73 }
74
setImageResource(PassOwnPtr<RenderImageResource> imageResource)75 void RenderImage::setImageResource(PassOwnPtr<RenderImageResource> imageResource)
76 {
77 ASSERT(!m_imageResource);
78 m_imageResource = imageResource;
79 m_imageResource->initialize(this);
80 }
81
82 // If we'll be displaying either alt text or an image, add some padding.
83 static const unsigned short paddingWidth = 4;
84 static const unsigned short paddingHeight = 4;
85
86 // Alt text is restricted to this maximum size, in pixels. These are
87 // signed integers because they are compared with other signed values.
88 static const float maxAltTextWidth = 1024;
89 static const int maxAltTextHeight = 256;
90
imageSizeForError(CachedImage * newImage) const91 IntSize RenderImage::imageSizeForError(CachedImage* newImage) const
92 {
93 ASSERT_ARG(newImage, newImage);
94 ASSERT_ARG(newImage, newImage->image());
95
96 // imageSize() returns 0 for the error image. We need the true size of the
97 // error image, so we have to get it by grabbing image() directly.
98 return IntSize(paddingWidth + newImage->image()->width() * style()->effectiveZoom(), paddingHeight + newImage->image()->height() * style()->effectiveZoom());
99 }
100
101 // Sets the image height and width to fit the alt text. Returns true if the
102 // image size changed.
setImageSizeForAltText(CachedImage * newImage)103 bool RenderImage::setImageSizeForAltText(CachedImage* newImage /* = 0 */)
104 {
105 IntSize imageSize;
106 if (newImage && newImage->image())
107 imageSize = imageSizeForError(newImage);
108 else if (!m_altText.isEmpty() || newImage) {
109 // If we'll be displaying either text or an image, add a little padding.
110 imageSize = IntSize(paddingWidth, paddingHeight);
111 }
112
113 // we have an alt and the user meant it (its not a text we invented)
114 if (!m_altText.isEmpty()) {
115 const Font& font = style()->font();
116 IntSize textSize(min(font.width(TextRun(m_altText.characters(), m_altText.length())), maxAltTextWidth), min(font.fontMetrics().height(), maxAltTextHeight));
117 imageSize = imageSize.expandedTo(textSize);
118 }
119
120 if (imageSize == intrinsicSize())
121 return false;
122
123 setIntrinsicSize(imageSize);
124 return true;
125 }
126
styleDidChange(StyleDifference diff,const RenderStyle * oldStyle)127 void RenderImage::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
128 {
129 RenderReplaced::styleDidChange(diff, oldStyle);
130 if (m_needsToSetSizeForAltText) {
131 if (!m_altText.isEmpty() && setImageSizeForAltText(m_imageResource->cachedImage()))
132 imageDimensionsChanged(true /* imageSizeChanged */);
133 m_needsToSetSizeForAltText = false;
134 }
135 }
136
imageChanged(WrappedImagePtr newImage,const IntRect * rect)137 void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
138 {
139 if (documentBeingDestroyed())
140 return;
141
142 if (hasBoxDecorations() || hasMask())
143 RenderReplaced::imageChanged(newImage, rect);
144
145 if (!m_imageResource)
146 return;
147
148 if (newImage != m_imageResource->imagePtr() || !newImage)
149 return;
150
151 bool imageSizeChanged = false;
152
153 // Set image dimensions, taking into account the size of the alt text.
154 if (m_imageResource->errorOccurred()) {
155 if (!m_altText.isEmpty() && document()->isPendingStyleRecalc()) {
156 ASSERT(node());
157 if (node()) {
158 m_needsToSetSizeForAltText = true;
159 node()->setNeedsStyleRecalc(SyntheticStyleChange);
160 }
161 return;
162 }
163 imageSizeChanged = setImageSizeForAltText(m_imageResource->cachedImage());
164 }
165
166 imageDimensionsChanged(imageSizeChanged, rect);
167 }
168
imageDimensionsChanged(bool imageSizeChanged,const IntRect * rect)169 void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* rect)
170 {
171 bool shouldRepaint = true;
172
173 if (m_imageResource->imageSize(style()->effectiveZoom()) != intrinsicSize() || imageSizeChanged) {
174 if (!m_imageResource->errorOccurred())
175 setIntrinsicSize(m_imageResource->imageSize(style()->effectiveZoom()));
176
177 // In the case of generated image content using :before/:after, we might not be in the
178 // render tree yet. In that case, we don't need to worry about check for layout, since we'll get a
179 // layout when we get added in to the render tree hierarchy later.
180 if (containingBlock()) {
181 // lets see if we need to relayout at all..
182 int oldwidth = width();
183 int oldheight = height();
184 if (!preferredLogicalWidthsDirty())
185 setPreferredLogicalWidthsDirty(true);
186 computeLogicalWidth();
187 computeLogicalHeight();
188
189 if (imageSizeChanged || width() != oldwidth || height() != oldheight) {
190 shouldRepaint = false;
191 if (!selfNeedsLayout())
192 setNeedsLayout(true);
193 }
194
195 setWidth(oldwidth);
196 setHeight(oldheight);
197 }
198 }
199
200 if (shouldRepaint) {
201 IntRect repaintRect;
202 if (rect) {
203 // The image changed rect is in source image coordinates (pre-zooming),
204 // so map from the bounds of the image to the contentsBox.
205 repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), m_imageResource->imageSize(1.0f)), contentBoxRect()));
206 // Guard against too-large changed rects.
207 repaintRect.intersect(contentBoxRect());
208 } else
209 repaintRect = contentBoxRect();
210
211 repaintRectangle(repaintRect);
212
213 #if USE(ACCELERATED_COMPOSITING)
214 if (hasLayer()) {
215 // Tell any potential compositing layers that the image needs updating.
216 layer()->contentChanged(RenderLayer::ImageChanged);
217 }
218 #endif
219 }
220 }
221
notifyFinished(CachedResource * newImage)222 void RenderImage::notifyFinished(CachedResource* newImage)
223 {
224 if (!m_imageResource)
225 return;
226
227 if (documentBeingDestroyed())
228 return;
229
230 #if USE(ACCELERATED_COMPOSITING)
231 if (newImage == m_imageResource->cachedImage() && hasLayer()) {
232 // tell any potential compositing layers
233 // that the image is done and they can reference it directly.
234 layer()->contentChanged(RenderLayer::ImageChanged);
235 }
236 #else
237 UNUSED_PARAM(newImage);
238 #endif
239 }
240
paintReplaced(PaintInfo & paintInfo,int tx,int ty)241 void RenderImage::paintReplaced(PaintInfo& paintInfo, int tx, int ty)
242 {
243 int cWidth = contentWidth();
244 int cHeight = contentHeight();
245 int leftBorder = borderLeft();
246 int topBorder = borderTop();
247 int leftPad = paddingLeft();
248 int topPad = paddingTop();
249
250 GraphicsContext* context = paintInfo.context;
251
252 if (!m_imageResource->hasImage() || m_imageResource->errorOccurred()) {
253 if (paintInfo.phase == PaintPhaseSelection)
254 return;
255
256 if (cWidth > 2 && cHeight > 2) {
257 // Draw an outline rect where the image should be.
258 #ifdef ANDROID_FIX // see http://b/issue?id=2052757
259 context->save();
260 #endif
261 context->setStrokeStyle(SolidStroke);
262 context->setStrokeColor(Color::lightGray, style()->colorSpace());
263 context->setFillColor(Color::transparent, style()->colorSpace());
264 context->drawRect(IntRect(tx + leftBorder + leftPad, ty + topBorder + topPad, cWidth, cHeight));
265 #ifdef ANDROID_FIX // see http://b/issue?id=2052757
266 context->restore();
267 #endif
268
269 bool errorPictureDrawn = false;
270 int imageX = 0;
271 int imageY = 0;
272 // When calculating the usable dimensions, exclude the pixels of
273 // the ouline rect so the error image/alt text doesn't draw on it.
274 int usableWidth = cWidth - 2;
275 int usableHeight = cHeight - 2;
276
277 RefPtr<Image> image = m_imageResource->image();
278
279 if (m_imageResource->errorOccurred() && !image->isNull() && usableWidth >= image->width() && usableHeight >= image->height()) {
280 // Center the error image, accounting for border and padding.
281 int centerX = (usableWidth - image->width()) / 2;
282 if (centerX < 0)
283 centerX = 0;
284 int centerY = (usableHeight - image->height()) / 2;
285 if (centerY < 0)
286 centerY = 0;
287 imageX = leftBorder + leftPad + centerX + 1;
288 imageY = topBorder + topPad + centerY + 1;
289 context->drawImage(image.get(), style()->colorSpace(), IntPoint(tx + imageX, ty + imageY));
290 errorPictureDrawn = true;
291 }
292
293 if (!m_altText.isEmpty()) {
294 String text = document()->displayStringModifiedByEncoding(m_altText);
295 context->setFillColor(style()->visitedDependentColor(CSSPropertyColor), style()->colorSpace());
296 int ax = tx + leftBorder + leftPad;
297 int ay = ty + topBorder + topPad;
298 const Font& font = style()->font();
299 const FontMetrics& fontMetrics = font.fontMetrics();
300 int ascent = fontMetrics.ascent();
301
302 // Only draw the alt text if it'll fit within the content box,
303 // and only if it fits above the error image.
304 TextRun textRun(text.characters(), text.length());
305 int textWidth = font.width(textRun);
306 if (errorPictureDrawn) {
307 if (usableWidth >= textWidth && fontMetrics.height() <= imageY)
308 context->drawText(font, textRun, IntPoint(ax, ay + ascent));
309 } else if (usableWidth >= textWidth && cHeight >= fontMetrics.height())
310 context->drawText(font, textRun, IntPoint(ax, ay + ascent));
311 }
312 }
313 } else if (m_imageResource->hasImage() && cWidth > 0 && cHeight > 0) {
314 RefPtr<Image> img = m_imageResource->image(cWidth, cHeight);
315 if (!img || img->isNull())
316 return;
317
318 #if PLATFORM(MAC)
319 if (style()->highlight() != nullAtom && !paintInfo.context->paintingDisabled())
320 paintCustomHighlight(tx - x(), ty - y(), style()->highlight(), true);
321 #endif
322
323 IntSize contentSize(cWidth, cHeight);
324 IntRect rect(IntPoint(tx + leftBorder + leftPad, ty + topBorder + topPad), contentSize);
325 paintIntoRect(context, rect);
326 }
327 }
328
paint(PaintInfo & paintInfo,int tx,int ty)329 void RenderImage::paint(PaintInfo& paintInfo, int tx, int ty)
330 {
331 RenderReplaced::paint(paintInfo, tx, ty);
332
333 if (paintInfo.phase == PaintPhaseOutline)
334 paintAreaElementFocusRing(paintInfo);
335 }
336
paintAreaElementFocusRing(PaintInfo & paintInfo)337 void RenderImage::paintAreaElementFocusRing(PaintInfo& paintInfo)
338 {
339 Document* document = this->document();
340
341 if (document->printing() || !document->frame()->selection()->isFocusedAndActive())
342 return;
343
344 if (paintInfo.context->paintingDisabled() && !paintInfo.context->updatingControlTints())
345 return;
346
347 Node* focusedNode = document->focusedNode();
348 if (!focusedNode || !focusedNode->hasTagName(areaTag))
349 return;
350
351 HTMLAreaElement* areaElement = static_cast<HTMLAreaElement*>(focusedNode);
352 if (areaElement->imageElement() != node())
353 return;
354
355 // Even if the theme handles focus ring drawing for entire elements, it won't do it for
356 // an area within an image, so we don't call RenderTheme::supportsFocusRing here.
357
358 Path path = areaElement->computePath(this);
359 if (path.isEmpty())
360 return;
361
362 // FIXME: Do we need additional code to clip the path to the image's bounding box?
363
364 RenderStyle* areaElementStyle = areaElement->computedStyle();
365 unsigned short outlineWidth = areaElementStyle->outlineWidth();
366 if (!outlineWidth)
367 return;
368
369 paintInfo.context->drawFocusRing(path, outlineWidth,
370 areaElementStyle->outlineOffset(),
371 areaElementStyle->visitedDependentColor(CSSPropertyOutlineColor));
372 }
373
areaElementFocusChanged(HTMLAreaElement * element)374 void RenderImage::areaElementFocusChanged(HTMLAreaElement* element)
375 {
376 ASSERT_UNUSED(element, element->imageElement() == node());
377
378 // It would be more efficient to only repaint the focus ring rectangle
379 // for the passed-in area element. That would require adding functions
380 // to the area element class.
381 repaint();
382 }
383
paintIntoRect(GraphicsContext * context,const IntRect & rect)384 void RenderImage::paintIntoRect(GraphicsContext* context, const IntRect& rect)
385 {
386 if (!m_imageResource->hasImage() || m_imageResource->errorOccurred() || rect.width() <= 0 || rect.height() <= 0)
387 return;
388
389 RefPtr<Image> img = m_imageResource->image(rect.width(), rect.height());
390 if (!img || img->isNull())
391 return;
392
393 HTMLImageElement* imageElt = (node() && node()->hasTagName(imgTag)) ? static_cast<HTMLImageElement*>(node()) : 0;
394 CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver;
395 Image* image = m_imageResource->image().get();
396 bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, rect.size());
397 context->drawImage(m_imageResource->image(rect.width(), rect.height()).get(), style()->colorSpace(), rect, compositeOperator, useLowQualityScaling);
398 }
399
minimumReplacedHeight() const400 int RenderImage::minimumReplacedHeight() const
401 {
402 return m_imageResource->errorOccurred() ? intrinsicSize().height() : 0;
403 }
404
imageMap() const405 HTMLMapElement* RenderImage::imageMap() const
406 {
407 HTMLImageElement* i = node() && node()->hasTagName(imgTag) ? static_cast<HTMLImageElement*>(node()) : 0;
408 return i ? i->document()->getImageMap(i->fastGetAttribute(usemapAttr)) : 0;
409 }
410
nodeAtPoint(const HitTestRequest & request,HitTestResult & result,int x,int y,int tx,int ty,HitTestAction hitTestAction)411 bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int x, int y, int tx, int ty, HitTestAction hitTestAction)
412 {
413 HitTestResult tempResult(result.point(), result.topPadding(), result.rightPadding(), result.bottomPadding(), result.leftPadding());
414 bool inside = RenderReplaced::nodeAtPoint(request, tempResult, x, y, tx, ty, hitTestAction);
415
416 if (tempResult.innerNode() && node()) {
417 if (HTMLMapElement* map = imageMap()) {
418 IntRect contentBox = contentBoxRect();
419 float zoom = style()->effectiveZoom();
420 int mapX = lroundf((x - tx - this->x() - contentBox.x()) / zoom);
421 int mapY = lroundf((y - ty - this->y() - contentBox.y()) / zoom);
422 if (map->mapMouseEvent(mapX, mapY, contentBox.size(), tempResult))
423 tempResult.setInnerNonSharedNode(node());
424 }
425 }
426
427 if (!inside && result.isRectBasedTest())
428 result.append(tempResult);
429 if (inside)
430 result = tempResult;
431 return inside;
432 }
433
updateAltText()434 void RenderImage::updateAltText()
435 {
436 if (!node())
437 return;
438
439 if (node()->hasTagName(inputTag))
440 m_altText = static_cast<HTMLInputElement*>(node())->altText();
441 else if (node()->hasTagName(imgTag))
442 m_altText = static_cast<HTMLImageElement*>(node())->altText();
443 #if ENABLE(WML)
444 else if (node()->hasTagName(WMLNames::imgTag))
445 m_altText = static_cast<WMLImageElement*>(node())->altText();
446 #endif
447 }
448
isLogicalWidthSpecified() const449 bool RenderImage::isLogicalWidthSpecified() const
450 {
451 switch (style()->logicalWidth().type()) {
452 case Fixed:
453 case Percent:
454 return true;
455 case Auto:
456 case Relative: // FIXME: Shouldn't this case return true?
457 case Intrinsic:
458 case MinIntrinsic:
459 return false;
460 }
461 ASSERT(false);
462 return false;
463 }
464
isLogicalHeightSpecified() const465 bool RenderImage::isLogicalHeightSpecified() const
466 {
467 switch (style()->logicalHeight().type()) {
468 case Fixed:
469 case Percent:
470 return true;
471 case Auto:
472 case Relative: // FIXME: Shouldn't this case return true?
473 case Intrinsic:
474 case MinIntrinsic:
475 return false;
476 }
477 ASSERT(false);
478 return false;
479 }
480
computeReplacedLogicalWidth(bool includeMaxWidth) const481 int RenderImage::computeReplacedLogicalWidth(bool includeMaxWidth) const
482 {
483 if (m_imageResource->imageHasRelativeWidth())
484 if (RenderObject* cb = isPositioned() ? container() : containingBlock()) {
485 if (cb->isBox())
486 m_imageResource->setImageContainerSize(IntSize(toRenderBox(cb)->availableWidth(), toRenderBox(cb)->availableHeight()));
487 }
488
489 int logicalWidth;
490 if (isLogicalWidthSpecified())
491 logicalWidth = computeReplacedLogicalWidthUsing(style()->logicalWidth());
492 else if (m_imageResource->usesImageContainerSize()) {
493 IntSize size = m_imageResource->imageSize(style()->effectiveZoom());
494 logicalWidth = style()->isHorizontalWritingMode() ? size.width() : size.height();
495 } else if (m_imageResource->imageHasRelativeWidth())
496 logicalWidth = 0; // If the image is relatively-sized, set the width to 0 until there is a set container size.
497 else
498 logicalWidth = calcAspectRatioLogicalWidth();
499
500 int minLogicalWidth = computeReplacedLogicalWidthUsing(style()->logicalMinWidth());
501 int maxLogicalWidth = !includeMaxWidth || style()->logicalMaxWidth().isUndefined() ? logicalWidth : computeReplacedLogicalWidthUsing(style()->logicalMaxWidth());
502
503 #ifdef ANDROID_LAYOUT
504 logicalWidth = max(minLogicalWidth, min(logicalWidth, maxLogicalWidth));
505 // in SSR mode, we will fit the image to its container width
506 if (document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) {
507 int cw = containingBlockLogicalWidthForContent();
508 if (cw && logicalWidth > cw)
509 logicalWidth = cw;
510 }
511 return logicalWidth;
512 #else
513 return max(minLogicalWidth, min(logicalWidth, maxLogicalWidth));
514 #endif
515 }
516
computeReplacedLogicalHeight() const517 int RenderImage::computeReplacedLogicalHeight() const
518 {
519 int logicalHeight;
520 if (isLogicalHeightSpecified())
521 logicalHeight = computeReplacedLogicalHeightUsing(style()->logicalHeight());
522 else if (m_imageResource->usesImageContainerSize()) {
523 IntSize size = m_imageResource->imageSize(style()->effectiveZoom());
524 logicalHeight = style()->isHorizontalWritingMode() ? size.height() : size.width();
525 } else if (m_imageResource->imageHasRelativeHeight())
526 logicalHeight = 0; // If the image is relatively-sized, set the height to 0 until there is a set container size.
527 else
528 logicalHeight = calcAspectRatioLogicalHeight();
529
530 int minLogicalHeight = computeReplacedLogicalHeightUsing(style()->logicalMinHeight());
531 int maxLogicalHeight = style()->logicalMaxHeight().isUndefined() ? logicalHeight : computeReplacedLogicalHeightUsing(style()->logicalMaxHeight());
532
533 #ifdef ANDROID_LAYOUT
534 logicalHeight = max(minLogicalHeight, min(logicalHeight, maxLogicalHeight));
535 // in SSR mode, we will fit the image to its container width
536 if (logicalHeight && document()->settings()->layoutAlgorithm() == Settings::kLayoutSSR) {
537 int logicalWidth;
538 if (isLogicalWidthSpecified())
539 logicalWidth = computeReplacedLogicalWidthUsing(style()->width());
540 else
541 logicalWidth = calcAspectRatioLogicalWidth();
542 int minLogicalWidth = computeReplacedLogicalWidthUsing(style()->minWidth());
543 int maxLogicalWidth = style()->maxWidth().value() == undefinedLength ? logicalWidth :
544 computeReplacedLogicalWidthUsing(style()->maxWidth());
545 logicalWidth = max(minLogicalWidth, min(logicalWidth, maxLogicalWidth));
546
547 int cw = containingBlockLogicalWidthForContent();
548 if (cw && logicalWidth && logicalWidth > cw)
549 logicalHeight = cw * logicalHeight / logicalWidth; // preserve aspect ratio
550 }
551 return logicalHeight;
552 #else
553 return max(minLogicalHeight, min(logicalHeight, maxLogicalHeight));
554 #endif
555 }
556
calcAspectRatioLogicalWidth() const557 int RenderImage::calcAspectRatioLogicalWidth() const
558 {
559 int intrinsicWidth = intrinsicLogicalWidth();
560 int intrinsicHeight = intrinsicLogicalHeight();
561 if (!intrinsicHeight)
562 return 0;
563 if (!m_imageResource->hasImage() || m_imageResource->errorOccurred())
564 return intrinsicWidth; // Don't bother scaling.
565 return RenderBox::computeReplacedLogicalHeight() * intrinsicWidth / intrinsicHeight;
566 }
567
calcAspectRatioLogicalHeight() const568 int RenderImage::calcAspectRatioLogicalHeight() const
569 {
570 int intrinsicWidth = intrinsicLogicalWidth();
571 int intrinsicHeight = intrinsicLogicalHeight();
572 if (!intrinsicWidth)
573 return 0;
574 if (!m_imageResource->hasImage() || m_imageResource->errorOccurred())
575 return intrinsicHeight; // Don't bother scaling.
576 return RenderBox::computeReplacedLogicalWidth() * intrinsicHeight / intrinsicWidth;
577 }
578
579 } // namespace WebCore
580