Commit 646caf2a authored by Daniel Hosseinian's avatar Daniel Hosseinian Committed by Commit Bot

PDF Viewer Update: Enable setting of thumbnail image

Adds a setter for the thumbnail element to accept an ImageData object
with which to paint the canvas of its thumbnail. The canvas is sized
according to the dimensions of the image and the screen resolution.

Bug: 652400
Change-Id: I885a1524cadd55731d90bfd0a8d2c4788beb1370
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2430728Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Reviewed-by: default avatardpapad <dpapad@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Commit-Queue: Daniel Hosseinian <dhoss@chromium.org>
Cr-Commit-Position: refs/heads/master@{#811406}
parent ba888e64
......@@ -905,6 +905,12 @@ IN_PROC_BROWSER_TEST_F(PDFExtensionJSUpdatesEnabledTest, ViewerThumbnailBar) {
RunTestsInJsModule("viewer_thumbnail_bar_test.js", "test.pdf");
}
IN_PROC_BROWSER_TEST_F(PDFExtensionJSUpdatesEnabledTest, ViewerThumbnail) {
// Although this test file does not require a PDF to be loaded, loading the
// elements without loading a PDF is difficult.
RunTestsInJsModule("viewer_thumbnail_test.js", "test.pdf");
}
class PDFExtensionJSTest : public PDFExtensionJSTestBase,
public testing::WithParamInterface<bool> {
public:
......
......@@ -4,17 +4,13 @@
}
#thumbnail {
/**
* TODO(crbug.com/652400): Remove div size and change inactive background
* color.
*/
/** TODO(crbug.com/652400): Change inactive background color. */
--inactive-background-color: black;
background-color: var(--inactive-background-color);
height: 140px;
display: inline-block;
margin-bottom: 12px;
margin-inline-end: auto;
margin-inline-start: auto;
width: 108px;
}
:host([is-active]) #thumbnail {
......@@ -22,11 +18,15 @@
background-color: var(--active-background-color);
}
canvas {
display: block;
}
#pageNumber {
line-height: 1;
}
</style>
<div id="content">
<div id="thumbnail" on-click="onClick_"></div>
<div id="pageNumber">[[pageNumber]]</div>
<div id="thumbnail" on-click="onClick_">
<canvas width="108" height="140"></canvas>
</div>
<div id="pageNumber">[[pageNumber]]</div>
......@@ -6,6 +6,14 @@ import './shared-css.js';
import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
// The maximum widths of thumbnails for each layout (px).
// These constants should be kept in sync with `kMaxWidthPortraitPx` and
// `kMaxWidthLandscapePx` in pdf/thumbnail.cc.
/** @type {number} */
const PORTRAIT_WIDTH = 108;
/** @type {number} */
const LANDSCAPE_WIDTH = 140;
export class ViewerThumbnailElement extends PolymerElement {
static get is() {
return 'viewer-thumbnail';
......@@ -27,6 +35,26 @@ export class ViewerThumbnailElement extends PolymerElement {
};
}
/** @param {!ImageData} imageData */
set image(imageData) {
const canvas = this.shadowRoot.querySelector('canvas');
canvas.width = imageData.width;
canvas.height = imageData.height;
// Resize the canvas CSS size to maintain the resolution of the thumbnail.
const isPortrait = canvas.width < canvas.height;
const cssWidth = Math.min(
isPortrait ? PORTRAIT_WIDTH : LANDSCAPE_WIDTH,
parseInt(canvas.width / window.devicePixelRatio, 10));
const scale = cssWidth / canvas.width;
const cssHeight = parseInt(canvas.height * scale, 10);
canvas.style.width = `${cssWidth}px`;
canvas.style.height = `${cssHeight}px`;
const ctx = canvas.getContext('2d');
ctx.putImageData(imageData, 0, 0);
}
/** @private */
isActiveChanged_() {
if (this.isActive) {
......
......@@ -39,6 +39,7 @@ js_type_check("closure_compile") {
":viewer_pdf_sidenav_test",
":viewer_pdf_toolbar_new_test",
":viewer_thumbnail_bar_test",
":viewer_thumbnail_test",
":viewport_test",
":whitespace_title_test",
......@@ -199,6 +200,14 @@ js_library("viewer_thumbnail_bar_test") {
externs_list = [ "$externs_path/test.js" ]
}
js_library("viewer_thumbnail_test") {
deps = [
"//chrome/browser/resources/pdf/elements:viewer-thumbnail",
"//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled",
]
externs_list = [ "$externs_path/test.js" ]
}
js_library("viewport_test") {
deps = [
":test_util",
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {ViewerThumbnailElement} from 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/elements/viewer-thumbnail.js';
/** @return {!ViewerThumbnailElement} */
function createThumbnail() {
document.body.innerHTML = '';
const thumbnail = /** @type {!ViewerThumbnailElement} */ (
document.createElement('viewer-thumbnail'));
document.body.appendChild(thumbnail);
return thumbnail;
}
/**
* @param {!ViewerThumbnailElement} thumbnail
* @param {!Array<number>} imageSize
* @param {!Array<number>} canvasSize
*/
function testThumbnailSize(thumbnail, imageSize, canvasSize) {
const imageData = new ImageData(imageSize[0], imageSize[1]);
thumbnail.image = imageData;
const canvas = thumbnail.shadowRoot.querySelector('canvas');
chrome.test.assertEq(`${canvasSize[0]}px`, canvas.style.width);
chrome.test.assertEq(`${canvasSize[1]}px`, canvas.style.height);
// The div containing the canvas should be resized to fit.
const div = canvas.parentElement;
chrome.test.assertEq(canvasSize[0], div.offsetWidth);
chrome.test.assertEq(canvasSize[1], div.offsetHeight);
}
const tests = [
function testSetNormalImageLowRes() {
window.devicePixelRatio = 1;
const thumbnail = createThumbnail();
[
// Letter portrait
{imageSize: [108, 140], canvasSize: [108, 140]},
// Letter landscape
{imageSize: [140, 108], canvasSize: [140, 108]},
// A4 portrait
{imageSize: [108, 152], canvasSize: [108, 152]},
// A4 portrait
{imageSize: [152, 108], canvasSize: [140, 99]},
].forEach(({
imageSize,
canvasSize,
}) => testThumbnailSize(thumbnail, imageSize, canvasSize));
chrome.test.succeed();
},
function testSetNormalImageHighRes() {
window.devicePixelRatio = 2;
const thumbnail = createThumbnail();
[
// Letter portrait
{imageSize: [216, 280], canvasSize: [108, 140]},
// Letter landscape
{imageSize: [280, 216], canvasSize: [140, 108]},
// A4 portrait
{imageSize: [216, 304], canvasSize: [108, 152]},
// A4 portrait
{imageSize: [304, 216], canvasSize: [140, 99]},
].forEach(({
imageSize,
canvasSize,
}) => testThumbnailSize(thumbnail, imageSize, canvasSize));
chrome.test.succeed();
},
function testSetExtremeImageLowRes() {
window.devicePixelRatio = 1;
const thumbnail = createThumbnail();
[
// The image should not scale to preserve its resolution.
{imageSize: [50, 1500], canvasSize: [50, 1500]},
// The image should scale down to fit in the sidenav.
{imageSize: [1500, 50], canvasSize: [140, 4]},
].forEach(({
imageSize,
canvasSize,
}) => testThumbnailSize(thumbnail, imageSize, canvasSize));
chrome.test.succeed();
},
function testSetExtremeImageHighRes() {
window.devicePixelRatio = 2;
const thumbnail = createThumbnail();
[
// The image should scale down to preserve its resolution.
{imageSize: [50, 1500], canvasSize: [25, 750]},
// The image should scale down to fit in the sidenav.
{imageSize: [1500, 50], canvasSize: [140, 4]},
].forEach(({
imageSize,
canvasSize,
}) => testThumbnailSize(thumbnail, imageSize, canvasSize));
chrome.test.succeed();
},
];
chrome.test.runTests(tests);
......@@ -34,6 +34,9 @@ constexpr int kImageColorChannels = 4;
constexpr int kMaxThumbnailPixels = 255 * 1024 / kImageColorChannels;
// Maximum CSS dimensions are set to match UX specifications.
// These constants should be kept in sync with `PORTRAIT_WIDTH` and
// `LANDSCAPE_WIDTH` in
// chrome/browser/resources/pdf/elements/viewer-thumbnail.js.
constexpr int kMaxWidthPortraitPx = 108;
constexpr int kMaxWidthLandscapePx = 140;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment