Index: Source/core/rendering/RenderImage.cpp |
diff --git a/Source/core/rendering/RenderImage.cpp b/Source/core/rendering/RenderImage.cpp |
index 921214316a9b8956ee23eee4222ba72c4a9c160a..db077fad99153215e255d46a12c1a08dea4e1dcc 100644 |
--- a/Source/core/rendering/RenderImage.cpp |
+++ b/Source/core/rendering/RenderImage.cpp |
@@ -59,6 +59,7 @@ |
, m_isGeneratedContent(false) |
, m_imageDevicePixelRatio(1.0f) |
{ |
+ updateAltText(); |
ResourceLoadPriorityOptimizer::resourceLoadPriorityOptimizer()->addRenderObject(this); |
} |
@@ -85,6 +86,58 @@ |
ASSERT(!m_imageResource); |
m_imageResource = imageResource; |
m_imageResource->initialize(this); |
+} |
+ |
+// Alt text is restricted to this maximum size, in pixels. These are |
+// signed integers because they are compared with other signed values. |
+static const float maxAltTextWidth = 1024; |
+static const int maxAltTextHeight = 256; |
+ |
+IntSize RenderImage::imageSizeForError(ImageResource* newImage) const |
+{ |
+ ASSERT_ARG(newImage, newImage); |
+ ASSERT_ARG(newImage, newImage->imageForRenderer(this)); |
+ |
+ IntSize imageSize; |
+ if (newImage->willPaintBrokenImage()) { |
+ float deviceScaleFactor = blink::deviceScaleFactor(frame()); |
+ pair<Image*, float> brokenImageAndImageScaleFactor = ImageResource::brokenImage(deviceScaleFactor); |
+ imageSize = brokenImageAndImageScaleFactor.first->size(); |
+ imageSize.scale(1 / brokenImageAndImageScaleFactor.second); |
+ } else |
+ imageSize = newImage->imageForRenderer(this)->size(); |
+ |
+ // imageSize() returns 0 for the error image. We need the true size of the |
+ // error image, so we have to get it by grabbing image() directly. |
+ return IntSize(paddingWidth + imageSize.width() * style()->effectiveZoom(), paddingHeight + imageSize.height() * style()->effectiveZoom()); |
+} |
+ |
+// Sets the image height and width to fit the alt text. Returns true if the |
+// image size changed. |
+bool RenderImage::setImageSizeForAltText(ImageResource* newImage /* = 0 */) |
+{ |
+ IntSize imageSize; |
+ if (newImage && newImage->imageForRenderer(this)) |
+ imageSize = imageSizeForError(newImage); |
+ else if (!m_altText.isEmpty() || newImage) { |
+ // If we'll be displaying either text or an image, add a little padding. |
+ imageSize = IntSize(paddingWidth, paddingHeight); |
+ } |
+ |
+ // we have an alt and the user meant it (its not a text we invented) |
+ if (!m_altText.isEmpty()) { |
+ FontCachePurgePreventer fontCachePurgePreventer; |
+ |
+ const Font& font = style()->font(); |
+ IntSize paddedTextSize(paddingWidth + std::min(ceilf(font.width(constructTextRun(this, font, m_altText, style()))), maxAltTextWidth), paddingHeight + std::min(font.fontMetrics().height(), maxAltTextHeight)); |
+ imageSize = imageSize.expandedTo(paddedTextSize); |
+ } |
+ |
+ if (imageSize == intrinsicSize()) |
+ return false; |
+ |
+ setIntrinsicSize(imageSize); |
+ return true; |
} |
void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect) |
@@ -112,7 +165,13 @@ |
m_didIncrementVisuallyNonEmptyPixelCount = true; |
} |
- repaintOrMarkForLayout(rect); |
+ bool imageSizeChanged = false; |
+ |
+ // Set image dimensions, taking into account the size of the alt text. |
+ if (m_imageResource->errorOccurred() || !newImage) |
+ imageSizeChanged = setImageSizeForAltText(m_imageResource->cachedImage()); |
+ |
+ paintInvalidationOrMarkForLayout(imageSizeChanged, rect); |
} |
void RenderImage::updateIntrinsicSizeIfNeeded(const LayoutSize& newSize) |
@@ -131,7 +190,7 @@ |
m_imageResource->setContainerSizeForRenderer(containerSize); |
} |
-void RenderImage::repaintOrMarkForLayout(const IntRect* rect) |
+void RenderImage::paintInvalidationOrMarkForLayout(bool imageSizeChangedToAccomodateAltText, const IntRect* rect) |
{ |
LayoutSize oldIntrinsicSize = intrinsicSize(); |
LayoutSize newIntrinsicSize = m_imageResource->intrinsicSize(style()->effectiveZoom()); |
@@ -144,7 +203,7 @@ |
if (!containingBlock()) |
return; |
- bool imageSourceHasChangedSize = oldIntrinsicSize != newIntrinsicSize; |
+ bool imageSourceHasChangedSize = oldIntrinsicSize != newIntrinsicSize || imageSizeChangedToAccomodateAltText; |
if (imageSourceHasChangedSize) |
setPreferredLogicalWidthsDirty(); |
@@ -240,7 +299,7 @@ |
paintInvalidationRect.moveBy(-absoluteContentBox().location()); |
paintInvalidationRect.inflate(outlineWidth); |
- repaintOrMarkForLayout(&paintInvalidationRect); |
+ paintInvalidationOrMarkForLayout(false, &paintInvalidationRect); |
} |
bool RenderImage::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox*) const |
@@ -321,6 +380,17 @@ |
if (inside) |
result = tempResult; |
return inside; |
+} |
+ |
+void RenderImage::updateAltText() |
+{ |
+ if (!node()) |
+ return; |
+ |
+ if (isHTMLInputElement(*node())) |
+ m_altText = toHTMLInputElement(node())->altText(); |
+ else if (isHTMLImageElement(*node())) |
+ m_altText = toHTMLImageElement(node())->altText(); |
} |
void RenderImage::layout() |