Add supports for view destinations with 'XYZ' fit type.
This CL adds supports for navigating to view destinations with fit type 'XYZ' (See table 151 in ISO 32000-1 standard for more details about syntax of "XYZ"), which specifies the coordinates of the page's origin inside the view window and the zoom factor of the page. Bug: 55776,748852 Change-Id: I4f449f006ec9dda4be282aea75c2a6e36a35b87e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2390997 Reviewed-by: Lei Zhang <thestig@chromium.org> Reviewed-by: Rebekah Potter <rbpotter@chromium.org> Commit-Queue: Hui Yingst <nigi@chromium.org> Cr-Commit-Position: refs/heads/master@{#810919}
This commit is contained in:
chrome
pdf
@ -31,6 +31,7 @@ export const FittingType = {
|
||||
/**
|
||||
* @typedef {{
|
||||
* messageId: string,
|
||||
* namedDestinationView: (string|undefined),
|
||||
* pageNumber: number,
|
||||
* }}
|
||||
*/
|
||||
|
@ -10,7 +10,8 @@ import {FittingType, NamedDestinationMessageData, Point} from './constants.js';
|
||||
* url: (string|undefined),
|
||||
* zoom: (number|undefined),
|
||||
* view: (!FittingType|undefined),
|
||||
* viewPosition: (!Point|undefined)
|
||||
* viewPosition: (!Point|undefined),
|
||||
* position: (!Object|undefined),
|
||||
* }}
|
||||
*/
|
||||
let OpenPdfParams;
|
||||
@ -99,6 +100,42 @@ export class OpenPdfParamsParser {
|
||||
return params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse view parameters which come from nameddest.
|
||||
* @param {string} paramValue view value.
|
||||
* @return {!OpenPdfParams} Map with view parameters.
|
||||
* @private
|
||||
*/
|
||||
parseNameddestViewParam_(paramValue) {
|
||||
const viewModeComponents = paramValue.toLowerCase().split(',');
|
||||
const viewMode = viewModeComponents[0];
|
||||
const params = {};
|
||||
|
||||
if (viewMode === 'xyz' && viewModeComponents.length === 4) {
|
||||
const x = parseFloat(viewModeComponents[1]);
|
||||
const y = parseFloat(viewModeComponents[2]);
|
||||
const zoom = parseFloat(viewModeComponents[3]);
|
||||
// If |x|, |y| or |zoom| is NaN, the values of the current positions and
|
||||
// zoom level are retained.
|
||||
if (!Number.isNaN(x) && !Number.isNaN(y) && !Number.isNaN(zoom)) {
|
||||
params['position'] = {x: x, y: y};
|
||||
// A zoom of 0 should be treated as a zoom of null (See table 151 in ISO
|
||||
// 32000-1 standard for more details about syntax of "XYZ".
|
||||
if (zoom !== 0) {
|
||||
params['zoom'] = zoom;
|
||||
}
|
||||
}
|
||||
return params;
|
||||
}
|
||||
|
||||
if (viewMode === 'fitr' && viewModeComponents.length === 5) {
|
||||
// TODO(crbug.com/535978): Add support for fit type "FitR" in nameddest.
|
||||
return params;
|
||||
}
|
||||
|
||||
return this.parseViewParam_(paramValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the parameters encoded in the fragment of a URL.
|
||||
* @param {string} url to parse
|
||||
@ -173,6 +210,12 @@ export class OpenPdfParamsParser {
|
||||
if (data.pageNumber !== -1) {
|
||||
params.page = data.pageNumber;
|
||||
}
|
||||
if (data.namedDestinationView) {
|
||||
Object.assign(
|
||||
params,
|
||||
this.parseNameddestViewParam_(
|
||||
/** @type {string} */ (data.namedDestinationView)));
|
||||
}
|
||||
callback(params);
|
||||
});
|
||||
} else {
|
||||
|
@ -22,9 +22,27 @@ const tests = [
|
||||
} else if (destination === 'UY') {
|
||||
return Promise.resolve(
|
||||
{messageId: 'getNamedDestination_3', pageNumber: 22});
|
||||
} else if (destination === 'DestWithXYZ') {
|
||||
return Promise.resolve({
|
||||
messageId: 'getNamedDestination_4',
|
||||
namedDestinationView: 'XYZ,111,222,1.7',
|
||||
pageNumber: 10
|
||||
});
|
||||
} else if (destination === 'DestWithXYZAtZoom0') {
|
||||
return Promise.resolve({
|
||||
messageId: 'getNamedDestination_5',
|
||||
namedDestinationView: 'XYZ,111,222,0',
|
||||
pageNumber: 10
|
||||
});
|
||||
} else if (destination === 'DestWithXYZWithNullParameter') {
|
||||
return Promise.resolve({
|
||||
messageId: 'getNamedDestination_6',
|
||||
namedDestinationView: 'XYZ,111,null,1.7',
|
||||
pageNumber: 13
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve(
|
||||
{messageId: 'getNamedDestination_4', pageNumber: -1});
|
||||
{messageId: 'getNamedDestination_7', pageNumber: -1});
|
||||
}
|
||||
});
|
||||
|
||||
@ -92,6 +110,38 @@ const tests = [
|
||||
chrome.test.assertEq(200, params.position.y);
|
||||
});
|
||||
|
||||
// Checking #nameddest=name with a nameddest that specifies the view fit
|
||||
// type is "XYZ" with multiple valid parameters.
|
||||
paramsParser.getViewportFromUrlParams(
|
||||
`${url}#nameddest=DestWithXYZ`, function(params) {
|
||||
chrome.test.assertEq(10, params.page);
|
||||
chrome.test.assertEq(1.7, params.zoom);
|
||||
chrome.test.assertEq(111, params.position.x);
|
||||
chrome.test.assertEq(222, params.position.y);
|
||||
chrome.test.assertEq(undefined, params.viewPosition);
|
||||
});
|
||||
|
||||
// Checking #nameddest=name with a nameddest that specifies the view fit
|
||||
// type is "XYZ" with a zoom parameter of 0.
|
||||
paramsParser.getViewportFromUrlParams(
|
||||
`${url}#nameddest=DestWithXYZAtZoom0`, function(params) {
|
||||
chrome.test.assertEq(10, params.page);
|
||||
chrome.test.assertEq(undefined, params.zoom);
|
||||
chrome.test.assertEq(111, params.position.x);
|
||||
chrome.test.assertEq(222, params.position.y);
|
||||
chrome.test.assertEq(undefined, params.viewPosition);
|
||||
});
|
||||
|
||||
// Checking #nameddest=name with a nameddest that specifies the view fit
|
||||
// type is "XYZ" and one of its parameters is null.
|
||||
paramsParser.getViewportFromUrlParams(
|
||||
`${url}#nameddest=DestWithXYZWithNullParameter`, function(params) {
|
||||
chrome.test.assertEq(13, params.page);
|
||||
chrome.test.assertEq(undefined, params.zoom);
|
||||
chrome.test.assertEq(undefined, params.position);
|
||||
chrome.test.assertEq(undefined, params.viewPosition);
|
||||
});
|
||||
|
||||
// Checking #view=Fit.
|
||||
paramsParser.getViewportFromUrlParams(`${url}#view=Fit`, function(params) {
|
||||
chrome.test.assertEq(FittingType.FIT_TO_PAGE, params.view);
|
||||
@ -142,6 +192,19 @@ const tests = [
|
||||
chrome.test.assertEq(undefined, params.view);
|
||||
chrome.test.assertEq(undefined, params.viewPosition);
|
||||
});
|
||||
// Checking #view=[wrong parameter].
|
||||
paramsParser.getViewportFromUrlParams(`${url}#view=XYZ`, function(params) {
|
||||
chrome.test.assertEq(undefined, params.view);
|
||||
chrome.test.assertEq(undefined, params.viewPosition);
|
||||
});
|
||||
// Checking #view=[wrong parameter],[position].
|
||||
paramsParser.getViewportFromUrlParams(
|
||||
`${url}#view=XYZ,111,222,1.7`, function(params) {
|
||||
chrome.test.assertEq(undefined, params.zoom);
|
||||
chrome.test.assertEq(undefined, params.position);
|
||||
chrome.test.assertEq(undefined, params.view);
|
||||
chrome.test.assertEq(undefined, params.viewPosition);
|
||||
});
|
||||
|
||||
// Checking #toolbar=0 to disable the toolbar.
|
||||
chrome.test.assertFalse(paramsParser.shouldShowToolbar(`${url}#toolbar=0`));
|
||||
|
@ -211,6 +211,7 @@ constexpr char kJSGetNamedDestination[] = "namedDestination";
|
||||
// Reply with the page number of the named destination (Plugin -> Page)
|
||||
constexpr char kJSGetNamedDestinationReplyType[] = "getNamedDestinationReply";
|
||||
constexpr char kJSNamedDestinationPageNumber[] = "pageNumber";
|
||||
constexpr char kJSNamedDestinationView[] = "namedDestinationView";
|
||||
|
||||
// Selecting text in document (Plugin -> Page)
|
||||
constexpr char kJSSetIsSelectingType[] = "setIsSelecting";
|
||||
@ -1652,6 +1653,16 @@ void OutOfProcessInstance::HandleGetNamedDestinationMessage(
|
||||
reply.Set(pp::Var(kJSNamedDestinationPageNumber),
|
||||
named_destination ? static_cast<int>(named_destination->page) : -1);
|
||||
reply.Set(pp::Var(kJSMessageId), dict.Get(pp::Var(kJSMessageId)).AsString());
|
||||
|
||||
// Handle named destination view.
|
||||
if (named_destination && !named_destination->view.empty()) {
|
||||
std::ostringstream view_stream;
|
||||
view_stream << named_destination->view;
|
||||
for (unsigned long i = 0; i < named_destination->num_params; ++i)
|
||||
view_stream << "," << named_destination->params[i];
|
||||
|
||||
reply.Set(pp::Var(kJSNamedDestinationView), view_stream.str());
|
||||
}
|
||||
PostMessage(reply);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user