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

Unified Diff: third_party/WebKit/Source/core/html/ImageDocument.cpp

Issue 2445413003: [Blink] Display images on a dark background (Closed)
Patch Set: Rebase Created 4 years, 1 month 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/core/html/ImageDocument.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/core/html/ImageDocument.cpp
diff --git a/third_party/WebKit/Source/core/html/ImageDocument.cpp b/third_party/WebKit/Source/core/html/ImageDocument.cpp
index a3d63fca4c7b905591e9d751fec82c526f22ccf4..88826f4d3894c9781ee2ab8eba50a45a760c2b64 100644
--- a/third_party/WebKit/Source/core/html/ImageDocument.cpp
+++ b/third_party/WebKit/Source/core/html/ImageDocument.cpp
@@ -54,6 +54,14 @@
using namespace std;
+namespace {
+
+// The base square size is set to 10 because it rounds nicely for both the
+// minimum scale (0.1) and maximum scale (5.0).
+const int kBaseCheckerSize = 10;
+
+} // namespace
+
namespace blink {
using namespace HTMLNames;
@@ -123,6 +131,13 @@ static String imageTitle(const String& filename, const IntSize& size) {
return result.toString();
}
+static LayoutSize cachedImageSize(HTMLImageElement* element) {
+ DCHECK(element->cachedImage());
+ return element->cachedImage()->imageSize(
+ LayoutObject::shouldRespectImageOrientation(element->layoutObject()),
+ 1.0f);
+}
+
void ImageDocumentParser::appendBytes(const char* data, size_t length) {
if (!length)
return;
@@ -155,10 +170,7 @@ void ImageDocumentParser::finish() {
// Report the natural image size in the page title, regardless of zoom
// level. At a zoom level of 1 the image is guaranteed to have an integer
// size.
- IntSize size = flooredIntSize(
- cachedImage->imageSize(LayoutObject::shouldRespectImageOrientation(
- document()->imageElement()->layoutObject()),
- 1.0f));
+ IntSize size = flooredIntSize(cachedImageSize(document()->imageElement()));
if (size.width()) {
// Compute the title, we use the decoded filename of the resource, falling
// back on the (decoded) hostname if there is no path.
@@ -172,6 +184,7 @@ void ImageDocumentParser::finish() {
}
document()->imageUpdated();
+ document()->imageLoaded();
}
if (!isDetached())
@@ -187,6 +200,8 @@ ImageDocument::ImageDocument(const DocumentInit& initializer)
m_imageSizeIsKnown(false),
m_didShrinkImage(false),
m_shouldShrinkImage(shouldShrinkToFit()),
+ m_imageIsLoaded(false),
+ m_checkerSize(0),
m_shrinkToFitMode(frame()->settings()->viewportEnabled() ? Viewport
: Desktop) {
setCompatibilityMode(QuirksMode);
@@ -218,9 +233,9 @@ void ImageDocument::createDocumentStructure() {
if (shouldShrinkToFit()) {
// Display the image prominently centered in the frame.
- body->setAttribute(styleAttr, "margin: 0px;");
+ body->setAttribute(styleAttr, "margin: 0px; background: #0e0e0e;");
- // See w3c example on how to centering an element:
+ // See w3c example on how to center an element:
// https://www.w3.org/Style/Examples/007/center.en.html
m_divElement = HTMLDivElement::create(*this);
m_divElement->setAttribute(styleAttr,
@@ -243,12 +258,8 @@ void ImageDocument::createDocumentStructure() {
willInsertBody();
- StringBuilder imageStyle;
- imageStyle.append("-webkit-user-select: none;");
- if (shouldShrinkToFit() && m_shrinkToFitMode == Viewport)
- imageStyle.append("max-width: 100%");
m_imageElement = HTMLImageElement::create(*this);
- m_imageElement->setAttribute(styleAttr, imageStyle.toAtomicString());
+ updateImageStyle();
m_imageElement->setLoadingImageDocument();
m_imageElement->setSrc(url().getString());
body->appendChild(m_imageElement.get());
@@ -260,9 +271,16 @@ void ImageDocument::createDocumentStructure() {
// Add event listeners
EventListener* listener = ImageEventListener::create(this);
if (LocalDOMWindow* domWindow = this->domWindow())
- domWindow->addEventListener("resize", listener, false);
- if (m_shrinkToFitMode == Desktop)
- m_imageElement->addEventListener("click", listener, false);
+ domWindow->addEventListener(EventTypeNames::resize, listener, false);
+
+ if (m_shrinkToFitMode == Desktop) {
+ m_imageElement->addEventListener(EventTypeNames::click, listener, false);
+ } else if (m_shrinkToFitMode == Viewport) {
+ m_imageElement->addEventListener(EventTypeNames::touchend, listener,
+ false);
+ m_imageElement->addEventListener(EventTypeNames::touchcancel, listener,
+ false);
+ }
}
rootElement->appendChild(head);
@@ -301,11 +319,7 @@ void ImageDocument::resizeImageToFit() {
if (!m_imageElement || m_imageElement->document() != this)
return;
- DCHECK(m_imageElement->cachedImage());
- LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(
- LayoutObject::shouldRespectImageOrientation(
- m_imageElement->layoutObject()),
- 1.f);
+ LayoutSize imageSize = cachedImageSize(m_imageElement);
const float scale = this->scale();
m_imageElement->setWidth(static_cast<int>(imageSize.width() * scale));
@@ -346,6 +360,77 @@ void ImageDocument::imageClicked(int x, int y) {
}
}
+void ImageDocument::imageLoaded() {
+ m_imageIsLoaded = true;
+
+ if (shouldShrinkToFit()) {
+ // The checkerboard background needs to be inserted.
+ updateImageStyle();
+ }
+}
+
+void ImageDocument::updateImageStyle() {
+ StringBuilder imageStyle;
+ imageStyle.append("-webkit-user-select: none;");
+
+ if (shouldShrinkToFit()) {
+ if (m_shrinkToFitMode == Viewport)
+ imageStyle.append("max-width: 100%;");
+
+ // Once the image has fully loaded, it is displayed atop a checkerboard to
+ // show transparency more faithfully. The pattern is generated via CSS.
+ if (m_imageIsLoaded) {
+ int newCheckerSize = kBaseCheckerSize;
+
+ if (m_shrinkToFitMode == Viewport) {
+ double scale;
+
+ if (hasFinishedParsing()) {
+ // To ensure the checker pattern is visible for large images, the
+ // checker size is dynamically adjusted to account for how much the
+ // page is currently being scaled.
+ scale = frame()->host()->visualViewport().scale();
+ } else {
+ // The checker pattern is initialized based on how large the image is
+ // relative to the viewport.
+ int viewportWidth = frame()->host()->visualViewport().size().width();
+ scale = viewportWidth / static_cast<double>(calculateDivWidth());
+ }
+
+ newCheckerSize = round(std::max(1.0, newCheckerSize / scale));
+ }
+
+ // The only thing that can differ between updates is the checker size.
+ if (newCheckerSize == m_checkerSize)
+ return;
+ m_checkerSize = newCheckerSize;
+
+ imageStyle.append("background-position: 0px 0px, ");
+ imageStyle.append(AtomicString::number(m_checkerSize));
+ imageStyle.append("px ");
+ imageStyle.append(AtomicString::number(m_checkerSize));
+ imageStyle.append("px;");
+
+ int tileSize = m_checkerSize * 2;
+ imageStyle.append("background-size: ");
+ imageStyle.append(AtomicString::number(tileSize));
+ imageStyle.append("px ");
+ imageStyle.append(AtomicString::number(tileSize));
+ imageStyle.append("px;");
+
+ imageStyle.append(
+ "background-color: white;"
+ "background-image:"
+ "linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, "
+ "#eee 75%, #eee 100%),"
+ "linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, "
+ "#eee 75%, #eee 100%);");
+ }
+ }
+
+ m_imageElement->setAttribute(styleAttr, imageStyle.toAtomicString());
+}
+
void ImageDocument::imageUpdated() {
DCHECK(m_imageElement);
@@ -377,10 +462,7 @@ void ImageDocument::restoreImageSize() {
return;
DCHECK(m_imageElement->cachedImage());
- LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(
- LayoutObject::shouldRespectImageOrientation(
- m_imageElement->layoutObject()),
- 1.0f);
+ LayoutSize imageSize = cachedImageSize(m_imageElement);
m_imageElement->setWidth(imageSize.width().toInt());
m_imageElement->setHeight(imageSize.height().toInt());
@@ -397,40 +479,42 @@ bool ImageDocument::imageFitsInWindow() const {
return this->scale() >= 1;
}
+int ImageDocument::calculateDivWidth() {
+ // Zooming in and out of an image being displayed within a viewport is done
+ // by changing the page scale factor of the page instead of changing the
+ // size of the image. The size of the image is set so that:
+ // * Images wider than the viewport take the full width of the screen.
+ // * Images taller than the viewport are initially aligned with the top of
+ // of the frame.
+ // * Images smaller in either dimension are centered along that axis.
+ LayoutSize imageSize = cachedImageSize(m_imageElement);
+ int viewportWidth = frame()->host()->visualViewport().size().width();
+
+ // For huge images, minimum-scale=0.1 is still too big on small screens.
+ // Set the <div> width so that the image will shrink to fit the width of the
+ // screen when the scale is minimum.
+ int maxWidth = std::min(imageSize.width().toInt(), viewportWidth * 10);
+ return std::max(viewportWidth, maxWidth);
+}
+
void ImageDocument::windowSizeChanged() {
if (!m_imageElement || !m_imageSizeIsKnown ||
m_imageElement->document() != this)
return;
if (m_shrinkToFitMode == Viewport) {
- // Zooming in and out of an image being displayed within a viewport is done
- // by changing the page scale factor of the page instead of changing the
- // size of the image. The size of the image is set so that:
- // * Images wider than the viewport take the full width of the screen.
- // * Images taller than the viewport are initially aligned with the top of
- // of the frame.
- // * Images smaller in either dimension are centered along that axis.
- LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(
- LayoutObject::shouldRespectImageOrientation(
- m_imageElement->layoutObject()),
- 1.f);
- int viewportWidth = frame()->host()->visualViewport().size().width();
- int viewportHeight = frame()->host()->visualViewport().size().height();
- float viewportAspectRatio = (float)viewportWidth / viewportHeight;
-
- // For huge images, minimum-scale=0.1 is still too big on small screens.
- // Set the <div> width so that the image will shrink to fit the width of the
- // screen when the scale is minimum.
- int maxWidth = std::min(imageSize.width().toInt(), viewportWidth * 10);
- int divWidth = std::max(viewportWidth, maxWidth);
+ LayoutSize imageSize = cachedImageSize(m_imageElement);
+ int divWidth = calculateDivWidth();
m_divElement->setInlineStyleProperty(CSSPropertyWidth, divWidth,
CSSPrimitiveValue::UnitType::Pixels);
// Explicitly set the height of the <div> containing the <img> so that it
// can display the full image without shrinking it, allowing a full-width
// reading mode for normal-width-huge-height images.
+ float viewportAspectRatio =
+ frame()->host()->visualViewport().size().aspectRatio();
int divHeight = std::max(imageSize.height().toInt(),
- (int)(divWidth / viewportAspectRatio));
+ static_cast<int>(divWidth / viewportAspectRatio));
m_divElement->setInlineStyleProperty(CSSPropertyHeight, divHeight,
CSSPrimitiveValue::UnitType::Pixels);
return;
@@ -495,6 +579,10 @@ void ImageEventListener::handleEvent(ExecutionContext*, Event* event) {
} else if (event->type() == EventTypeNames::click && event->isMouseEvent()) {
MouseEvent* mouseEvent = toMouseEvent(event);
m_doc->imageClicked(mouseEvent->x(), mouseEvent->y());
+ } else if ((event->type() == EventTypeNames::touchend ||
+ event->type() == EventTypeNames::touchcancel) &&
+ event->isTouchEvent()) {
+ m_doc->updateImageStyle();
}
}
« no previous file with comments | « third_party/WebKit/Source/core/html/ImageDocument.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698