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

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

Issue 2646663002: [Blink] Don't center images in Android WebViews (Closed)
Patch Set: Fixing comments Created 3 years, 11 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 30 matching lines...) Expand all
41 #include "core/html/HTMLDivElement.h" 41 #include "core/html/HTMLDivElement.h"
42 #include "core/html/HTMLHeadElement.h" 42 #include "core/html/HTMLHeadElement.h"
43 #include "core/html/HTMLHtmlElement.h" 43 #include "core/html/HTMLHtmlElement.h"
44 #include "core/html/HTMLImageElement.h" 44 #include "core/html/HTMLImageElement.h"
45 #include "core/html/HTMLMetaElement.h" 45 #include "core/html/HTMLMetaElement.h"
46 #include "core/layout/LayoutObject.h" 46 #include "core/layout/LayoutObject.h"
47 #include "core/loader/DocumentLoader.h" 47 #include "core/loader/DocumentLoader.h"
48 #include "core/loader/FrameLoader.h" 48 #include "core/loader/FrameLoader.h"
49 #include "core/loader/FrameLoaderClient.h" 49 #include "core/loader/FrameLoaderClient.h"
50 #include "core/loader/resource/ImageResource.h" 50 #include "core/loader/resource/ImageResource.h"
51 #include "core/page/Page.h"
51 #include "platform/HostWindow.h" 52 #include "platform/HostWindow.h"
52 #include "wtf/text/StringBuilder.h" 53 #include "wtf/text/StringBuilder.h"
53 #include <limits> 54 #include <limits>
54 55
55 using namespace std; 56 using namespace std;
56 57
57 namespace { 58 namespace {
58 59
59 // The base square size is set to 10 because it rounds nicely for both the 60 // The base square size is set to 10 because it rounds nicely for both the
60 // minimum scale (0.1) and maximum scale (5.0). 61 // minimum scale (0.1) and maximum scale (5.0).
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 return; // runScriptsAtDocumentElementAvailable can detach the frame. 229 return; // runScriptsAtDocumentElementAvailable can detach the frame.
229 230
230 HTMLHeadElement* head = HTMLHeadElement::create(*this); 231 HTMLHeadElement* head = HTMLHeadElement::create(*this);
231 HTMLMetaElement* meta = HTMLMetaElement::create(*this); 232 HTMLMetaElement* meta = HTMLMetaElement::create(*this);
232 meta->setAttribute(nameAttr, "viewport"); 233 meta->setAttribute(nameAttr, "viewport");
233 meta->setAttribute(contentAttr, "width=device-width, minimum-scale=0.1"); 234 meta->setAttribute(contentAttr, "width=device-width, minimum-scale=0.1");
234 head->appendChild(meta); 235 head->appendChild(meta);
235 236
236 HTMLBodyElement* body = HTMLBodyElement::create(*this); 237 HTMLBodyElement* body = HTMLBodyElement::create(*this);
237 238
238 if (shouldShrinkToFit()) { 239 if (shouldCenterImage()) {
239 // Display the image prominently centered in the frame. 240 // Display the image prominently centered in the frame.
240 body->setAttribute(styleAttr, "margin: 0px; background: #0e0e0e;"); 241 body->setAttribute(styleAttr, "margin: 0px; background: #0e0e0e;");
241 242
242 // See w3c example on how to center an element: 243 // See w3c example on how to center an element:
243 // https://www.w3.org/Style/Examples/007/center.en.html 244 // https://www.w3.org/Style/Examples/007/center.en.html
244 m_divElement = HTMLDivElement::create(*this); 245 m_divElement = HTMLDivElement::create(*this);
245 m_divElement->setAttribute(styleAttr, 246 m_divElement->setAttribute(styleAttr,
246 "display: flex;" 247 "display: flex;"
247 "flex-direction: column;" 248 "flex-direction: column;"
248 "justify-content: center;" 249 "justify-content: center;"
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
285 false); 286 false);
286 m_imageElement->addEventListener(EventTypeNames::touchcancel, listener, 287 m_imageElement->addEventListener(EventTypeNames::touchcancel, listener,
287 false); 288 false);
288 } 289 }
289 } 290 }
290 291
291 rootElement->appendChild(head); 292 rootElement->appendChild(head);
292 rootElement->appendChild(body); 293 rootElement->appendChild(body);
293 } 294 }
294 295
296 bool ImageDocument::shouldCenterImage() const {
297 bool isAndroidWebView =
298 page() ? page()->settings().getWideViewportQuirkEnabled() : false;
299 return shouldShrinkToFit() && !isAndroidWebView;
300 }
301
295 float ImageDocument::scale() const { 302 float ImageDocument::scale() const {
296 DCHECK_EQ(m_shrinkToFitMode, Desktop); 303 DCHECK_EQ(m_shrinkToFitMode, Desktop);
297 if (!m_imageElement || m_imageElement->document() != this) 304 if (!m_imageElement || m_imageElement->document() != this)
298 return 1.0f; 305 return 1.0f;
299 306
300 FrameView* view = frame()->view(); 307 FrameView* view = frame()->view();
301 if (!view) 308 if (!view)
302 return 1.0f; 309 return 1.0f;
303 310
304 DCHECK(m_imageElement->cachedImage()); 311 DCHECK(m_imageElement->cachedImage());
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 // The checkerboard background needs to be inserted. 379 // The checkerboard background needs to be inserted.
373 updateImageStyle(); 380 updateImageStyle();
374 } 381 }
375 } 382 }
376 383
377 void ImageDocument::updateImageStyle() { 384 void ImageDocument::updateImageStyle() {
378 StringBuilder imageStyle; 385 StringBuilder imageStyle;
379 imageStyle.append("-webkit-user-select: none;"); 386 imageStyle.append("-webkit-user-select: none;");
380 387
381 if (shouldShrinkToFit()) { 388 if (shouldShrinkToFit()) {
382 if (m_shrinkToFitMode == Viewport) 389 if (shouldCenterImage() && m_shrinkToFitMode == Viewport) {
390 // The image occupies the full width of its parent <div>.
383 imageStyle.append("max-width: 100%;"); 391 imageStyle.append("max-width: 100%;");
392 }
384 393
385 // Once the image has fully loaded, it is displayed atop a checkerboard to
386 // show transparency more faithfully. The pattern is generated via CSS.
387 if (m_imageIsLoaded) { 394 if (m_imageIsLoaded) {
388 int newCheckerSize = kBaseCheckerSize; 395 int newCheckerSize = kBaseCheckerSize;
389 MouseCursorMode newCursorMode = Default; 396 MouseCursorMode newCursorMode = Default;
390 397
398 // Images are displayed atop a checkerboard to show transparency more
399 // faithfully. The pattern is generated via CSS.
391 if (m_shrinkToFitMode == Viewport) { 400 if (m_shrinkToFitMode == Viewport) {
392 double scale; 401 if (shouldCenterImage()) {
402 double scale;
393 403
394 if (hasFinishedParsing()) { 404 if (hasFinishedParsing()) {
395 // To ensure the checker pattern is visible for large images, the 405 // To ensure the checker pattern is visible for large images, the
396 // checker size is dynamically adjusted to account for how much the 406 // checker size is dynamically adjusted to account for how much the
397 // page is currently being scaled. 407 // page is currently being scaled.
398 scale = frame()->host()->visualViewport().scale(); 408 scale = frame()->host()->visualViewport().scale();
399 } else { 409 } else {
400 // The checker pattern is initialized based on how large the image is 410 // The checker pattern is initialized based on how large the image
401 // relative to the viewport. 411 // is relative to the viewport.
402 int viewportWidth = frame()->host()->visualViewport().size().width(); 412 int viewportWidth =
403 scale = viewportWidth / static_cast<double>(calculateDivWidth()); 413 frame()->host()->visualViewport().size().width();
414 scale = viewportWidth / static_cast<double>(calculateDivWidth());
415 }
416
417 newCheckerSize = std::round(std::max(1.0, newCheckerSize / scale));
404 } 418 }
405
406 newCheckerSize = std::round(std::max(1.0, newCheckerSize / scale));
407 } else { 419 } else {
408 // In desktop mode, the user can click on the image to zoom in or out. 420 // In desktop mode, the user can click on the image to zoom in or out.
409 DCHECK_EQ(m_shrinkToFitMode, Desktop); 421 DCHECK_EQ(m_shrinkToFitMode, Desktop);
410 if (imageFitsInWindow()) { 422 if (imageFitsInWindow()) {
411 newCursorMode = Default; 423 newCursorMode = Default;
412 } else { 424 } else {
413 newCursorMode = m_shouldShrinkImage ? ZoomIn : ZoomOut; 425 newCursorMode = m_shouldShrinkImage ? ZoomIn : ZoomOut;
414 } 426 }
415 } 427 }
416 428
417 // The only things that can differ between updates are checker size and 429 // The only things that can differ between updates are checker size and
418 // the type of cursor being displayed. 430 // the type of cursor being displayed.
419 if (newCheckerSize == m_styleCheckerSize && 431 if (newCheckerSize == m_styleCheckerSize &&
420 newCursorMode == m_styleMouseCursorMode) { 432 newCursorMode == m_styleMouseCursorMode) {
421 return; 433 return;
422 } 434 }
423 m_styleCheckerSize = newCheckerSize; 435 m_styleCheckerSize = newCheckerSize;
424 m_styleMouseCursorMode = newCursorMode; 436 m_styleMouseCursorMode = newCursorMode;
425 437
426 imageStyle.append("background-position: 0px 0px, "); 438 // Generate the new image style string.
427 imageStyle.append(AtomicString::number(m_styleCheckerSize)); 439 if (shouldCenterImage()) {
428 imageStyle.append("px "); 440 imageStyle.append("background-position: 0px 0px, ");
429 imageStyle.append(AtomicString::number(m_styleCheckerSize)); 441 imageStyle.append(AtomicString::number(m_styleCheckerSize));
430 imageStyle.append("px;"); 442 imageStyle.append("px ");
443 imageStyle.append(AtomicString::number(m_styleCheckerSize));
444 imageStyle.append("px;");
431 445
432 int tileSize = m_styleCheckerSize * 2; 446 int tileSize = m_styleCheckerSize * 2;
433 imageStyle.append("background-size: "); 447 imageStyle.append("background-size: ");
434 imageStyle.append(AtomicString::number(tileSize)); 448 imageStyle.append(AtomicString::number(tileSize));
435 imageStyle.append("px "); 449 imageStyle.append("px ");
436 imageStyle.append(AtomicString::number(tileSize)); 450 imageStyle.append(AtomicString::number(tileSize));
437 imageStyle.append("px;"); 451 imageStyle.append("px;");
438 452
439 // Generating the checkerboard pattern this way is not exactly cheap. 453 // Generating the checkerboard pattern this way is not exactly cheap.
440 // If rasterization performance becomes an issue, we could look at using 454 // If rasterization performance becomes an issue, we could look at using
441 // a cheaper shader (e.g. pre-generate a scaled tile + base64-encode + 455 // a cheaper shader (e.g. pre-generate a scaled tile + base64-encode +
442 // inline dataURI => single bitmap shader). 456 // inline dataURI => single bitmap shader).
443 imageStyle.append( 457 imageStyle.append(
444 "background-image:" 458 "background-image:"
445 "linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, " 459 "linear-gradient(45deg, #eee 25%, transparent 25%, transparent "
446 "#eee 75%, #eee 100%)," 460 "75%, "
447 "linear-gradient(45deg, #eee 25%, white 25%, white 75%, " 461 "#eee 75%, #eee 100%),"
448 "#eee 75%, #eee 100%);"); 462 "linear-gradient(45deg, #eee 25%, white 25%, white 75%, "
463 "#eee 75%, #eee 100%);");
464 }
449 465
450 if (m_shrinkToFitMode == Desktop) { 466 if (m_shrinkToFitMode == Desktop) {
451 if (m_styleMouseCursorMode == ZoomIn) 467 if (m_styleMouseCursorMode == ZoomIn)
452 imageStyle.append("cursor: zoom-in;"); 468 imageStyle.append("cursor: zoom-in;");
453 else if (m_styleMouseCursorMode == ZoomOut) 469 else if (m_styleMouseCursorMode == ZoomOut)
454 imageStyle.append("cursor: zoom-out;"); 470 imageStyle.append("cursor: zoom-out;");
455 } 471 }
456 } 472 }
457 } 473 }
458 474
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
520 int maxWidth = std::min(imageSize.width().toInt(), viewportWidth * 10); 536 int maxWidth = std::min(imageSize.width().toInt(), viewportWidth * 10);
521 return std::max(viewportWidth, maxWidth); 537 return std::max(viewportWidth, maxWidth);
522 } 538 }
523 539
524 void ImageDocument::windowSizeChanged() { 540 void ImageDocument::windowSizeChanged() {
525 if (!m_imageElement || !m_imageSizeIsKnown || 541 if (!m_imageElement || !m_imageSizeIsKnown ||
526 m_imageElement->document() != this) 542 m_imageElement->document() != this)
527 return; 543 return;
528 544
529 if (m_shrinkToFitMode == Viewport) { 545 if (m_shrinkToFitMode == Viewport) {
530 LayoutSize imageSize = cachedImageSize(m_imageElement); 546 if (shouldCenterImage()) {
531 int divWidth = calculateDivWidth(); 547 // Set the size of the <div> containing the <img>. The latter is set
532 m_divElement->setInlineStyleProperty(CSSPropertyWidth, divWidth, 548 // to occupy 100% of the <div>'s width in updateImageStyle().
533 CSSPrimitiveValue::UnitType::Pixels); 549 LayoutSize imageSize = cachedImageSize(m_imageElement);
550 int divWidth = calculateDivWidth();
551 m_divElement->setInlineStyleProperty(CSSPropertyWidth, divWidth,
552 CSSPrimitiveValue::UnitType::Pixels);
534 553
535 // Explicitly set the height of the <div> containing the <img> so that it 554 // Explicitly set the height of the <div> containing the <img> so that it
536 // can display the full image without shrinking it, allowing a full-width 555 // can display the full image without shrinking it, allowing a full-width
537 // reading mode for normal-width-huge-height images. 556 // reading mode for normal-width-huge-height images.
538 float viewportAspectRatio = 557 float viewportAspectRatio =
539 frame()->host()->visualViewport().size().aspectRatio(); 558 frame()->host()->visualViewport().size().aspectRatio();
540 int divHeight = std::max(imageSize.height().toInt(), 559 int divHeight =
541 static_cast<int>(divWidth / viewportAspectRatio)); 560 std::max(imageSize.height().toInt(),
542 m_divElement->setInlineStyleProperty(CSSPropertyHeight, divHeight, 561 static_cast<int>(divWidth / viewportAspectRatio));
543 CSSPrimitiveValue::UnitType::Pixels); 562 m_divElement->setInlineStyleProperty(CSSPropertyHeight, divHeight,
563 CSSPrimitiveValue::UnitType::Pixels);
564 } else {
565 // Set the max width of the <img> to prevent it from becoming too large.
566 // See calculateDivWidth() for details.
567 int viewportWidth = frame()->host()->visualViewport().size().width();
568 m_imageElement->setInlineStyleProperty(
aelias_OOO_until_Jul13 2017/01/19 00:23:49 Could you try instead returning false from ImageDo
569 CSSPropertyMaxWidth, viewportWidth * 10,
570 CSSPrimitiveValue::UnitType::Pixels);
571 }
544 return; 572 return;
545 } 573 }
546 574
547 bool fitsInWindow = imageFitsInWindow(); 575 bool fitsInWindow = imageFitsInWindow();
548 576
549 // If the image has been explicitly zoomed in, restore the cursor if the image 577 // If the image has been explicitly zoomed in, restore the cursor if the image
550 // fits and set it to a zoom out cursor if the image doesn't fit 578 // fits and set it to a zoom out cursor if the image doesn't fit
551 if (!m_shouldShrinkImage) { 579 if (!m_shouldShrinkImage) {
552 updateImageStyle(); 580 updateImageStyle();
553 return; 581 return;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
619 } 647 }
620 648
621 bool ImageEventListener::operator==(const EventListener& listener) const { 649 bool ImageEventListener::operator==(const EventListener& listener) const {
622 if (const ImageEventListener* imageEventListener = 650 if (const ImageEventListener* imageEventListener =
623 ImageEventListener::cast(&listener)) 651 ImageEventListener::cast(&listener))
624 return m_doc == imageEventListener->m_doc; 652 return m_doc == imageEventListener->m_doc;
625 return false; 653 return false;
626 } 654 }
627 655
628 } // namespace blink 656 } // 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