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

Side by Side Diff: third_party/WebKit/Source/core/html/ImageDocument.cpp

Issue 2376163002: [Blink] Display images in the center of the screen (Closed)
Patch Set: Rebasing Created 4 years, 2 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 | « third_party/WebKit/Source/core/html/ImageDocument.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. 2 * Copyright (C) 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 1. Redistributions of source code must retain the above copyright 7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright 9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
(...skipping 20 matching lines...) Expand all
31 #include "core/events/MouseEvent.h" 31 #include "core/events/MouseEvent.h"
32 #include "core/fetch/ImageResource.h" 32 #include "core/fetch/ImageResource.h"
33 #include "core/frame/FrameHost.h" 33 #include "core/frame/FrameHost.h"
34 #include "core/frame/FrameView.h" 34 #include "core/frame/FrameView.h"
35 #include "core/frame/LocalDOMWindow.h" 35 #include "core/frame/LocalDOMWindow.h"
36 #include "core/frame/LocalFrame.h" 36 #include "core/frame/LocalFrame.h"
37 #include "core/frame/Settings.h" 37 #include "core/frame/Settings.h"
38 #include "core/frame/UseCounter.h" 38 #include "core/frame/UseCounter.h"
39 #include "core/frame/VisualViewport.h" 39 #include "core/frame/VisualViewport.h"
40 #include "core/html/HTMLBodyElement.h" 40 #include "core/html/HTMLBodyElement.h"
41 #include "core/html/HTMLContentElement.h"
42 #include "core/html/HTMLDivElement.h"
41 #include "core/html/HTMLHeadElement.h" 43 #include "core/html/HTMLHeadElement.h"
42 #include "core/html/HTMLHtmlElement.h" 44 #include "core/html/HTMLHtmlElement.h"
43 #include "core/html/HTMLImageElement.h" 45 #include "core/html/HTMLImageElement.h"
44 #include "core/html/HTMLMetaElement.h" 46 #include "core/html/HTMLMetaElement.h"
45 #include "core/layout/LayoutObject.h" 47 #include "core/layout/LayoutObject.h"
46 #include "core/loader/DocumentLoader.h" 48 #include "core/loader/DocumentLoader.h"
47 #include "core/loader/FrameLoader.h" 49 #include "core/loader/FrameLoader.h"
48 #include "core/loader/FrameLoaderClient.h" 50 #include "core/loader/FrameLoaderClient.h"
49 #include "platform/HostWindow.h" 51 #include "platform/HostWindow.h"
50 #include "wtf/text/StringBuilder.h" 52 #include "wtf/text/StringBuilder.h"
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 } 175 }
174 176
175 if (!isDetached()) 177 if (!isDetached())
176 document()->finishedParsing(); 178 document()->finishedParsing();
177 } 179 }
178 180
179 // -------- 181 // --------
180 182
181 ImageDocument::ImageDocument(const DocumentInit& initializer) 183 ImageDocument::ImageDocument(const DocumentInit& initializer)
182 : HTMLDocument(initializer, ImageDocumentClass), 184 : HTMLDocument(initializer, ImageDocumentClass),
185 m_divElement(nullptr),
183 m_imageElement(nullptr), 186 m_imageElement(nullptr),
184 m_imageSizeIsKnown(false), 187 m_imageSizeIsKnown(false),
185 m_didShrinkImage(false), 188 m_didShrinkImage(false),
186 m_shouldShrinkImage(shouldShrinkToFit()), 189 m_shouldShrinkImage(shouldShrinkToFit()),
187 m_shrinkToFitMode(frame()->settings()->viewportEnabled() ? Viewport 190 m_shrinkToFitMode(frame()->settings()->viewportEnabled() ? Viewport
188 : Desktop) { 191 : Desktop) {
189 setCompatibilityMode(QuirksMode); 192 setCompatibilityMode(QuirksMode);
190 lockCompatibilityMode(); 193 lockCompatibilityMode();
191 UseCounter::count(*this, UseCounter::ImageDocument); 194 UseCounter::count(*this, UseCounter::ImageDocument);
192 if (!isInMainFrame()) 195 if (!isInMainFrame())
(...skipping 12 matching lines...) Expand all
205 if (isStopped()) 208 if (isStopped())
206 return; // runScriptsAtDocumentElementAvailable can detach the frame. 209 return; // runScriptsAtDocumentElementAvailable can detach the frame.
207 210
208 HTMLHeadElement* head = HTMLHeadElement::create(*this); 211 HTMLHeadElement* head = HTMLHeadElement::create(*this);
209 HTMLMetaElement* meta = HTMLMetaElement::create(*this); 212 HTMLMetaElement* meta = HTMLMetaElement::create(*this);
210 meta->setAttribute(nameAttr, "viewport"); 213 meta->setAttribute(nameAttr, "viewport");
211 meta->setAttribute(contentAttr, "width=device-width, minimum-scale=0.1"); 214 meta->setAttribute(contentAttr, "width=device-width, minimum-scale=0.1");
212 head->appendChild(meta); 215 head->appendChild(meta);
213 216
214 HTMLBodyElement* body = HTMLBodyElement::create(*this); 217 HTMLBodyElement* body = HTMLBodyElement::create(*this);
215 body->setAttribute(styleAttr, "margin: 0px;"); 218
219 if (shouldShrinkToFit()) {
220 // Display the image prominently centered in the frame.
221 body->setAttribute(styleAttr, "margin: 0px;");
222
223 // See w3c example on how to centering an element:
224 // https://www.w3.org/Style/Examples/007/center.en.html
225 m_divElement = HTMLDivElement::create(*this);
226 m_divElement->setAttribute(styleAttr,
227 "display: flex;"
228 "flex-direction: column;"
229 "justify-content: center;"
230 "align-items: center;"
231 "min-height: min-content;"
232 "min-width: min-content;"
233 "height: 100%;"
234 "width: 100%;");
235 HTMLContentElement* content = HTMLContentElement::create(*this);
236 m_divElement->appendChild(content);
237
238 ShadowRoot& shadowRoot = body->ensureUserAgentShadowRoot();
239 shadowRoot.appendChild(m_divElement);
240 } else {
241 body->setAttribute(styleAttr, "margin: 0px;");
242 }
216 243
217 willInsertBody(); 244 willInsertBody();
218 245
246 StringBuilder imageStyle;
247 imageStyle.append("-webkit-user-select: none;");
248 if (shouldShrinkToFit() && m_shrinkToFitMode == Viewport)
249 imageStyle.append("max-width: 100%");
219 m_imageElement = HTMLImageElement::create(*this); 250 m_imageElement = HTMLImageElement::create(*this);
220 m_imageElement->setAttribute(styleAttr, "-webkit-user-select: none"); 251 m_imageElement->setAttribute(styleAttr, imageStyle.toAtomicString());
221 m_imageElement->setLoadingImageDocument(); 252 m_imageElement->setLoadingImageDocument();
222 m_imageElement->setSrc(url().getString()); 253 m_imageElement->setSrc(url().getString());
223 body->appendChild(m_imageElement.get()); 254 body->appendChild(m_imageElement.get());
224 if (loader() && m_imageElement->cachedImage()) 255 if (loader() && m_imageElement->cachedImage())
225 m_imageElement->cachedImage()->responseReceived(loader()->response(), 256 m_imageElement->cachedImage()->responseReceived(loader()->response(),
226 nullptr); 257 nullptr);
227 258
228 if (shouldShrinkToFit()) { 259 if (shouldShrinkToFit()) {
229 // Add event listeners 260 // Add event listeners
230 EventListener* listener = ImageEventListener::create(this); 261 EventListener* listener = ImageEventListener::create(this);
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
287 DCHECK_EQ(m_shrinkToFitMode, Desktop); 318 DCHECK_EQ(m_shrinkToFitMode, Desktop);
288 319
289 if (!m_imageSizeIsKnown || imageFitsInWindow()) 320 if (!m_imageSizeIsKnown || imageFitsInWindow())
290 return; 321 return;
291 322
292 m_shouldShrinkImage = !m_shouldShrinkImage; 323 m_shouldShrinkImage = !m_shouldShrinkImage;
293 324
294 if (m_shouldShrinkImage) { 325 if (m_shouldShrinkImage) {
295 windowSizeChanged(); 326 windowSizeChanged();
296 } else { 327 } else {
328 // Adjust the coordinates to account for the fact that the image was
329 // centered on the screen.
330 float imageX = x - m_imageElement->offsetLeft();
331 float imageY = y - m_imageElement->offsetTop();
332
297 restoreImageSize(); 333 restoreImageSize();
298 334
299 updateStyleAndLayout(); 335 updateStyleAndLayout();
300 336
301 double scale = this->scale(); 337 double scale = this->scale();
302 338
303 float scrollX = 339 float scrollX =
304 x / scale - static_cast<float>(frame()->view()->width()) / 2; 340 imageX / scale - static_cast<float>(frame()->view()->width()) / 2;
305 float scrollY = 341 float scrollY =
306 y / scale - static_cast<float>(frame()->view()->height()) / 2; 342 imageY / scale - static_cast<float>(frame()->view()->height()) / 2;
307 343
308 frame()->view()->layoutViewportScrollableArea()->setScrollOffset( 344 frame()->view()->layoutViewportScrollableArea()->setScrollOffset(
309 ScrollOffset(scrollX, scrollY), ProgrammaticScroll); 345 ScrollOffset(scrollX, scrollY), ProgrammaticScroll);
310 } 346 }
311 } 347 }
312 348
313 void ImageDocument::imageUpdated() { 349 void ImageDocument::imageUpdated() {
314 DCHECK(m_imageElement); 350 DCHECK(m_imageElement);
315 351
316 if (m_imageSizeIsKnown) 352 if (m_imageSizeIsKnown)
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
360 DCHECK_EQ(m_shrinkToFitMode, Desktop); 396 DCHECK_EQ(m_shrinkToFitMode, Desktop);
361 return this->scale() >= 1; 397 return this->scale() >= 1;
362 } 398 }
363 399
364 void ImageDocument::windowSizeChanged() { 400 void ImageDocument::windowSizeChanged() {
365 if (!m_imageElement || !m_imageSizeIsKnown || 401 if (!m_imageElement || !m_imageSizeIsKnown ||
366 m_imageElement->document() != this) 402 m_imageElement->document() != this)
367 return; 403 return;
368 404
369 if (m_shrinkToFitMode == Viewport) { 405 if (m_shrinkToFitMode == Viewport) {
406 // Zooming in and out of an image being displayed within a viewport is done
407 // by changing the page scale factor of the page instead of changing the
408 // size of the image. The size of the image is set so that:
409 // * Images wider than the viewport take the full width of the screen.
410 // * Images taller than the viewport are initially aligned with the top of
411 // of the frame.
412 // * Images smaller in either dimension are centered along that axis.
413 LayoutSize imageSize = m_imageElement->cachedImage()->imageSize(
414 LayoutObject::shouldRespectImageOrientation(
415 m_imageElement->layoutObject()),
416 1.f);
417 int viewportWidth = frame()->host()->visualViewport().size().width();
418 int viewportHeight = frame()->host()->visualViewport().size().height();
419 float viewportAspectRatio = (float)viewportWidth / viewportHeight;
420
370 // For huge images, minimum-scale=0.1 is still too big on small screens. 421 // For huge images, minimum-scale=0.1 is still too big on small screens.
371 // Set max-width so that the image will shrink to fit the width of the 422 // Set the <div> width so that the image will shrink to fit the width of the
372 // screen when the scale is minimum. Don't shrink height to fit because we 423 // screen when the scale is minimum.
373 // use width=device-width in viewport meta tag, and expect a full-width 424 int maxWidth = std::min(imageSize.width().toInt(), viewportWidth * 10);
425 int divWidth = std::max(viewportWidth, maxWidth);
426 m_divElement->setInlineStyleProperty(CSSPropertyWidth, divWidth,
427 CSSPrimitiveValue::UnitType::Pixels);
428
429 // Explicitly set the height of the <div> containing the <img> so that it
430 // can display the full image without shrinking it, allowing a full-width
374 // reading mode for normal-width-huge-height images. 431 // reading mode for normal-width-huge-height images.
375 int viewportWidth = frame()->host()->visualViewport().size().width(); 432 int divHeight = std::max(imageSize.height().toInt(),
376 m_imageElement->setInlineStyleProperty(CSSPropertyMaxWidth, 433 (int)(divWidth / viewportAspectRatio));
377 viewportWidth * 10, 434 m_divElement->setInlineStyleProperty(CSSPropertyHeight, divHeight,
378 CSSPrimitiveValue::UnitType::Pixels); 435 CSSPrimitiveValue::UnitType::Pixels);
379 return; 436 return;
380 } 437 }
381 438
382 bool fitsInWindow = imageFitsInWindow(); 439 bool fitsInWindow = imageFitsInWindow();
383 440
384 // If the image has been explicitly zoomed in, restore the cursor if the image 441 // If the image has been explicitly zoomed in, restore the cursor if the image
385 // fits and set it to a zoom out cursor if the image doesn't fit 442 // fits and set it to a zoom out cursor if the image doesn't fit
386 if (!m_shouldShrinkImage) { 443 if (!m_shouldShrinkImage) {
387 if (fitsInWindow) 444 if (fitsInWindow)
388 m_imageElement->removeInlineStyleProperty(CSSPropertyCursor); 445 m_imageElement->removeInlineStyleProperty(CSSPropertyCursor);
(...skipping 29 matching lines...) Expand all
418 } 475 }
419 476
420 return m_imageElement->cachedImage(); 477 return m_imageElement->cachedImage();
421 } 478 }
422 479
423 bool ImageDocument::shouldShrinkToFit() const { 480 bool ImageDocument::shouldShrinkToFit() const {
424 return frame()->isMainFrame(); 481 return frame()->isMainFrame();
425 } 482 }
426 483
427 DEFINE_TRACE(ImageDocument) { 484 DEFINE_TRACE(ImageDocument) {
485 visitor->trace(m_divElement);
428 visitor->trace(m_imageElement); 486 visitor->trace(m_imageElement);
429 HTMLDocument::trace(visitor); 487 HTMLDocument::trace(visitor);
430 } 488 }
431 489
432 // -------- 490 // --------
433 491
434 void ImageEventListener::handleEvent(ExecutionContext*, Event* event) { 492 void ImageEventListener::handleEvent(ExecutionContext*, Event* event) {
435 if (event->type() == EventTypeNames::resize) { 493 if (event->type() == EventTypeNames::resize) {
436 m_doc->windowSizeChanged(); 494 m_doc->windowSizeChanged();
437 } else if (event->type() == EventTypeNames::click && event->isMouseEvent()) { 495 } else if (event->type() == EventTypeNames::click && event->isMouseEvent()) {
438 MouseEvent* mouseEvent = toMouseEvent(event); 496 MouseEvent* mouseEvent = toMouseEvent(event);
439 m_doc->imageClicked(mouseEvent->x(), mouseEvent->y()); 497 m_doc->imageClicked(mouseEvent->x(), mouseEvent->y());
440 } 498 }
441 } 499 }
442 500
443 bool ImageEventListener::operator==(const EventListener& listener) const { 501 bool ImageEventListener::operator==(const EventListener& listener) const {
444 if (const ImageEventListener* imageEventListener = 502 if (const ImageEventListener* imageEventListener =
445 ImageEventListener::cast(&listener)) 503 ImageEventListener::cast(&listener))
446 return m_doc == imageEventListener->m_doc; 504 return m_doc == imageEventListener->m_doc;
447 return false; 505 return false;
448 } 506 }
449 507
450 } // namespace blink 508 } // namespace blink
OLDNEW
« 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