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

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

Issue 2445413003: [Blink] Display images on a dark background (Closed)
Patch Set: Rebasing 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 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
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * 12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 19 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
20 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 20 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 22 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */ 23 */
24 24
25 #include "core/html/ImageDocument.h" 25 #include "core/html/ImageDocument.h"
26 26
27 #include "bindings/core/v8/ExceptionStatePlaceholder.h" 27 #include "bindings/core/v8/ExceptionStatePlaceholder.h"
28 #include "core/HTMLNames.h" 28 #include "core/HTMLNames.h"
29 #include "core/dom/ExecutionContextTask.h"
29 #include "core/dom/RawDataDocumentParser.h" 30 #include "core/dom/RawDataDocumentParser.h"
30 #include "core/events/EventListener.h" 31 #include "core/events/EventListener.h"
31 #include "core/events/MouseEvent.h" 32 #include "core/events/MouseEvent.h"
32 #include "core/fetch/ImageResource.h" 33 #include "core/fetch/ImageResource.h"
33 #include "core/frame/FrameHost.h" 34 #include "core/frame/FrameHost.h"
34 #include "core/frame/FrameView.h" 35 #include "core/frame/FrameView.h"
35 #include "core/frame/LocalDOMWindow.h" 36 #include "core/frame/LocalDOMWindow.h"
36 #include "core/frame/LocalFrame.h" 37 #include "core/frame/LocalFrame.h"
37 #include "core/frame/Settings.h" 38 #include "core/frame/Settings.h"
38 #include "core/frame/UseCounter.h" 39 #include "core/frame/UseCounter.h"
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 String fileName = 166 String fileName =
166 decodeURLEscapeSequences(document()->url().lastPathComponent()); 167 decodeURLEscapeSequences(document()->url().lastPathComponent());
167 if (fileName.isEmpty()) 168 if (fileName.isEmpty())
168 fileName = document()->url().host(); 169 fileName = document()->url().host();
169 document()->setTitle(imageTitle(fileName, size)); 170 document()->setTitle(imageTitle(fileName, size));
170 if (isDetached()) 171 if (isDetached())
171 return; 172 return;
172 } 173 }
173 174
174 document()->imageUpdated(); 175 document()->imageUpdated();
176 document()->imageLoaded();
175 } 177 }
176 178
177 if (!isDetached()) 179 if (!isDetached())
178 document()->finishedParsing(); 180 document()->finishedParsing();
179 } 181 }
180 182
181 // -------- 183 // --------
182 184
183 ImageDocument::ImageDocument(const DocumentInit& initializer) 185 ImageDocument::ImageDocument(const DocumentInit& initializer)
184 : HTMLDocument(initializer, ImageDocumentClass), 186 : HTMLDocument(initializer, ImageDocumentClass),
185 m_divElement(nullptr), 187 m_divElement(nullptr),
186 m_imageElement(nullptr), 188 m_imageElement(nullptr),
187 m_imageSizeIsKnown(false), 189 m_imageSizeIsKnown(false),
188 m_didShrinkImage(false), 190 m_didShrinkImage(false),
189 m_shouldShrinkImage(shouldShrinkToFit()), 191 m_shouldShrinkImage(shouldShrinkToFit()),
192 m_imageIsLoaded(false),
190 m_shrinkToFitMode(frame()->settings()->viewportEnabled() ? Viewport 193 m_shrinkToFitMode(frame()->settings()->viewportEnabled() ? Viewport
191 : Desktop) { 194 : Desktop) {
192 setCompatibilityMode(QuirksMode); 195 setCompatibilityMode(QuirksMode);
193 lockCompatibilityMode(); 196 lockCompatibilityMode();
194 UseCounter::count(*this, UseCounter::ImageDocument); 197 UseCounter::count(*this, UseCounter::ImageDocument);
195 if (!isInMainFrame()) 198 if (!isInMainFrame())
196 UseCounter::count(*this, UseCounter::ImageDocumentInFrame); 199 UseCounter::count(*this, UseCounter::ImageDocumentInFrame);
197 } 200 }
198 201
199 DocumentParser* ImageDocument::createParser() { 202 DocumentParser* ImageDocument::createParser() {
(...skipping 11 matching lines...) Expand all
211 HTMLHeadElement* head = HTMLHeadElement::create(*this); 214 HTMLHeadElement* head = HTMLHeadElement::create(*this);
212 HTMLMetaElement* meta = HTMLMetaElement::create(*this); 215 HTMLMetaElement* meta = HTMLMetaElement::create(*this);
213 meta->setAttribute(nameAttr, "viewport"); 216 meta->setAttribute(nameAttr, "viewport");
214 meta->setAttribute(contentAttr, "width=device-width, minimum-scale=0.1"); 217 meta->setAttribute(contentAttr, "width=device-width, minimum-scale=0.1");
215 head->appendChild(meta); 218 head->appendChild(meta);
216 219
217 HTMLBodyElement* body = HTMLBodyElement::create(*this); 220 HTMLBodyElement* body = HTMLBodyElement::create(*this);
218 221
219 if (shouldShrinkToFit()) { 222 if (shouldShrinkToFit()) {
220 // Display the image prominently centered in the frame. 223 // Display the image prominently centered in the frame.
221 body->setAttribute(styleAttr, "margin: 0px;"); 224 body->setAttribute(styleAttr, "margin: 0px; background: #0e0e0e;");
222 225
223 // See w3c example on how to centering an element: 226 // See w3c example on how to center an element:
224 // https://www.w3.org/Style/Examples/007/center.en.html 227 // https://www.w3.org/Style/Examples/007/center.en.html
225 m_divElement = HTMLDivElement::create(*this); 228 m_divElement = HTMLDivElement::create(*this);
226 m_divElement->setAttribute(styleAttr, 229 m_divElement->setAttribute(styleAttr,
227 "display: flex;" 230 "display: flex;"
228 "flex-direction: column;" 231 "flex-direction: column;"
229 "justify-content: center;" 232 "justify-content: center;"
230 "align-items: center;" 233 "align-items: center;"
231 "min-height: min-content;" 234 "min-height: min-content;"
232 "min-width: min-content;" 235 "min-width: min-content;"
233 "height: 100%;" 236 "height: 100%;"
234 "width: 100%;"); 237 "width: 100%;");
235 HTMLContentElement* content = HTMLContentElement::create(*this); 238 HTMLContentElement* content = HTMLContentElement::create(*this);
236 m_divElement->appendChild(content); 239 m_divElement->appendChild(content);
237 240
238 ShadowRoot& shadowRoot = body->ensureUserAgentShadowRoot(); 241 ShadowRoot& shadowRoot = body->ensureUserAgentShadowRoot();
239 shadowRoot.appendChild(m_divElement); 242 shadowRoot.appendChild(m_divElement);
240 } else { 243 } else {
241 body->setAttribute(styleAttr, "margin: 0px;"); 244 body->setAttribute(styleAttr, "margin: 0px;");
242 } 245 }
243 246
244 willInsertBody(); 247 willInsertBody();
245 248
246 StringBuilder imageStyle;
247 imageStyle.append("-webkit-user-select: none;");
248 if (shouldShrinkToFit() && m_shrinkToFitMode == Viewport)
249 imageStyle.append("max-width: 100%");
250 m_imageElement = HTMLImageElement::create(*this); 249 m_imageElement = HTMLImageElement::create(*this);
251 m_imageElement->setAttribute(styleAttr, imageStyle.toAtomicString()); 250 updateImageStyle();
252 m_imageElement->setLoadingImageDocument(); 251 m_imageElement->setLoadingImageDocument();
253 m_imageElement->setSrc(url().getString()); 252 m_imageElement->setSrc(url().getString());
254 body->appendChild(m_imageElement.get()); 253 body->appendChild(m_imageElement.get());
255 if (loader() && m_imageElement->cachedImage()) 254 if (loader() && m_imageElement->cachedImage())
256 m_imageElement->cachedImage()->responseReceived(loader()->response(), 255 m_imageElement->cachedImage()->responseReceived(loader()->response(),
257 nullptr); 256 nullptr);
258 257
259 if (shouldShrinkToFit()) { 258 if (shouldShrinkToFit()) {
260 // Add event listeners 259 // Add event listeners
261 EventListener* listener = ImageEventListener::create(this); 260 EventListener* listener = ImageEventListener::create(this);
262 if (LocalDOMWindow* domWindow = this->domWindow()) 261 if (LocalDOMWindow* domWindow = this->domWindow())
263 domWindow->addEventListener("resize", listener, false); 262 domWindow->addEventListener(EventTypeNames::resize, listener, false);
264 if (m_shrinkToFitMode == Desktop) 263
265 m_imageElement->addEventListener("click", listener, false); 264 if (m_shrinkToFitMode == Desktop) {
265 m_imageElement->addEventListener(EventTypeNames::click, listener, false);
266 } else if (m_shrinkToFitMode == Viewport) {
267 m_imageElement->addEventListener(EventTypeNames::touchend, listener,
268 false);
269 m_imageElement->addEventListener(EventTypeNames::touchcancel, listener,
270 false);
271 }
266 } 272 }
267 273
268 rootElement->appendChild(head); 274 rootElement->appendChild(head);
269 rootElement->appendChild(body); 275 rootElement->appendChild(body);
270 } 276 }
271 277
272 float ImageDocument::scale() const { 278 float ImageDocument::scale() const {
273 DCHECK_EQ(m_shrinkToFitMode, Desktop); 279 DCHECK_EQ(m_shrinkToFitMode, Desktop);
274 if (!m_imageElement || m_imageElement->document() != this) 280 if (!m_imageElement || m_imageElement->document() != this)
275 return 1.0f; 281 return 1.0f;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 float scrollX = 345 float scrollX =
340 imageX / scale - static_cast<float>(frame()->view()->width()) / 2; 346 imageX / scale - static_cast<float>(frame()->view()->width()) / 2;
341 float scrollY = 347 float scrollY =
342 imageY / scale - static_cast<float>(frame()->view()->height()) / 2; 348 imageY / scale - static_cast<float>(frame()->view()->height()) / 2;
343 349
344 frame()->view()->layoutViewportScrollableArea()->setScrollOffset( 350 frame()->view()->layoutViewportScrollableArea()->setScrollOffset(
345 ScrollOffset(scrollX, scrollY), ProgrammaticScroll); 351 ScrollOffset(scrollX, scrollY), ProgrammaticScroll);
346 } 352 }
347 } 353 }
348 354
355 static void updateDocumentImageStyle(ExecutionContext* context) {
356 // Shouldn't be anything except an ImageDocument if |context| is a Document.
357 ImageDocument* document = static_cast<ImageDocument*>(toDocument(context));
358 document->updateImageStyle();
359 }
360
361 void ImageDocument::imageLoaded() {
362 m_imageIsLoaded = true;
363 postTask(BLINK_FROM_HERE, createSameThreadTask(&updateDocumentImageStyle),
pdr. 2016/11/01 06:54:56 This seems reasonable to me if we don't have anoth
gone 2016/11/02 18:42:20 Got rid of the task and tried looking at more flag
364 "updateImageStyle");
365 }
366
367 void ImageDocument::updateImageStyle() {
368 StringBuilder imageStyle;
pdr. 2016/11/01 06:54:56 Because this is called on every touch end/cancel e
gone 2016/11/02 18:42:20 WDYT about this version, where I compare the two s
369 imageStyle.append("-webkit-user-select: none;");
370 if (shouldShrinkToFit()) {
371 if (m_shrinkToFitMode == Viewport) {
372 imageStyle.append("max-width: 100%;");
373 }
374
375 // Once the image has fully loaded, it is displayed atop a checkerboard to
376 // show transparency more faithfully. The pattern is generated via CSS.
377 if (m_imageIsLoaded) {
378 // The base square size is set to 10 because it rounds nicely for both the
379 // minimum scale (0.1) and maximum scale (5.0).
380 double checkerSize = 10.0;
381
382 if (m_shrinkToFitMode == Viewport) {
383 // To ensure the checker pattern is visible for large images in
384 // viewports, the checker size must be dynamically adjusted to account
385 // for how much the page is currently being scaled.
386 double scale = frame()->host()->visualViewport().scale();
387 checkerSize = std::max(1.0, checkerSize / scale);
388 }
389
390 int roundedSize = static_cast<int>(round(checkerSize));
391 int tileSize = roundedSize * 2;
392
393 imageStyle.append("background-position: 0px 0px, ");
394 imageStyle.append(AtomicString::number(roundedSize));
395 imageStyle.append("px ");
396 imageStyle.append(AtomicString::number(roundedSize));
397 imageStyle.append("px;");
398
399 imageStyle.append("background-size: ");
400 imageStyle.append(AtomicString::number(tileSize));
401 imageStyle.append("px ");
402 imageStyle.append(AtomicString::number(tileSize));
403 imageStyle.append("px;");
404
405 imageStyle.append(
406 "background-color: white;"
407 "background-image:"
408 "linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, "
409 "#eee 75%, #eee 100%),"
410 "linear-gradient(45deg, #eee 25%, transparent 25%, transparent 75%, "
411 "#eee 75%, #eee 100%);");
412 }
413 }
414
415 m_imageElement->setAttribute(styleAttr, imageStyle.toAtomicString());
416 }
417
349 void ImageDocument::imageUpdated() { 418 void ImageDocument::imageUpdated() {
350 DCHECK(m_imageElement); 419 DCHECK(m_imageElement);
351 420
352 if (m_imageSizeIsKnown) 421 if (m_imageSizeIsKnown)
353 return; 422 return;
354 423
355 updateStyleAndLayoutTree(); 424 updateStyleAndLayoutTree();
356 if (!m_imageElement->cachedImage() || 425 if (!m_imageElement->cachedImage() ||
357 m_imageElement->cachedImage() 426 m_imageElement->cachedImage()
358 ->imageSize(LayoutObject::shouldRespectImageOrientation( 427 ->imageSize(LayoutObject::shouldRespectImageOrientation(
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 // screen when the scale is minimum. 492 // screen when the scale is minimum.
424 int maxWidth = std::min(imageSize.width().toInt(), viewportWidth * 10); 493 int maxWidth = std::min(imageSize.width().toInt(), viewportWidth * 10);
425 int divWidth = std::max(viewportWidth, maxWidth); 494 int divWidth = std::max(viewportWidth, maxWidth);
426 m_divElement->setInlineStyleProperty(CSSPropertyWidth, divWidth, 495 m_divElement->setInlineStyleProperty(CSSPropertyWidth, divWidth,
427 CSSPrimitiveValue::UnitType::Pixels); 496 CSSPrimitiveValue::UnitType::Pixels);
428 497
429 // Explicitly set the height of the <div> containing the <img> so that it 498 // 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 499 // can display the full image without shrinking it, allowing a full-width
431 // reading mode for normal-width-huge-height images. 500 // reading mode for normal-width-huge-height images.
432 int divHeight = std::max(imageSize.height().toInt(), 501 int divHeight = std::max(imageSize.height().toInt(),
433 (int)(divWidth / viewportAspectRatio)); 502 static_cast<int>(divWidth / viewportAspectRatio));
434 m_divElement->setInlineStyleProperty(CSSPropertyHeight, divHeight, 503 m_divElement->setInlineStyleProperty(CSSPropertyHeight, divHeight,
435 CSSPrimitiveValue::UnitType::Pixels); 504 CSSPrimitiveValue::UnitType::Pixels);
505 updateImageStyle();
436 return; 506 return;
437 } 507 }
438 508
439 bool fitsInWindow = imageFitsInWindow(); 509 bool fitsInWindow = imageFitsInWindow();
440 510
441 // If the image has been explicitly zoomed in, restore the cursor if the image 511 // If the image has been explicitly zoomed in, restore the cursor if the image
442 // fits and set it to a zoom out cursor if the image doesn't fit 512 // fits and set it to a zoom out cursor if the image doesn't fit
443 if (!m_shouldShrinkImage) { 513 if (!m_shouldShrinkImage) {
444 if (fitsInWindow) 514 if (fitsInWindow)
445 m_imageElement->removeInlineStyleProperty(CSSPropertyCursor); 515 m_imageElement->removeInlineStyleProperty(CSSPropertyCursor);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
488 } 558 }
489 559
490 // -------- 560 // --------
491 561
492 void ImageEventListener::handleEvent(ExecutionContext*, Event* event) { 562 void ImageEventListener::handleEvent(ExecutionContext*, Event* event) {
493 if (event->type() == EventTypeNames::resize) { 563 if (event->type() == EventTypeNames::resize) {
494 m_doc->windowSizeChanged(); 564 m_doc->windowSizeChanged();
495 } else if (event->type() == EventTypeNames::click && event->isMouseEvent()) { 565 } else if (event->type() == EventTypeNames::click && event->isMouseEvent()) {
496 MouseEvent* mouseEvent = toMouseEvent(event); 566 MouseEvent* mouseEvent = toMouseEvent(event);
497 m_doc->imageClicked(mouseEvent->x(), mouseEvent->y()); 567 m_doc->imageClicked(mouseEvent->x(), mouseEvent->y());
568 } else if (event->isTouchEvent()) {
569 m_doc->updateImageStyle();
498 } 570 }
499 } 571 }
500 572
501 bool ImageEventListener::operator==(const EventListener& listener) const { 573 bool ImageEventListener::operator==(const EventListener& listener) const {
502 if (const ImageEventListener* imageEventListener = 574 if (const ImageEventListener* imageEventListener =
503 ImageEventListener::cast(&listener)) 575 ImageEventListener::cast(&listener))
504 return m_doc == imageEventListener->m_doc; 576 return m_doc == imageEventListener->m_doc;
505 return false; 577 return false;
506 } 578 }
507 579
508 } // namespace blink 580 } // 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