From 4ed3290cde6178ba4dbebeb085a86a2e83fffd44 Mon Sep 17 00:00:00 2001 From: Nikischin Date: Sun, 2 Jun 2024 13:16:39 +0200 Subject: [PATCH 1/3] Possible fix for dpi (untested) --- packages/layout/src/page/getSize.js | 15 --------------- packages/layout/src/steps/resolveStyles.js | 2 +- packages/stylesheet/src/transform/units.js | 2 +- 3 files changed, 2 insertions(+), 17 deletions(-) diff --git a/packages/layout/src/page/getSize.js b/packages/layout/src/page/getSize.js index 76ee76aa6..6db1191a5 100644 --- a/packages/layout/src/page/getSize.js +++ b/packages/layout/src/page/getSize.js @@ -70,18 +70,6 @@ const toSizeObject = (v) => ({ width: v[0], height: v[1] }); */ const flipSizeObject = (v) => ({ width: v.height, height: v.width }); -/** - * Adjust page size to passed DPI - * - * @param {{ width: number, height: number }} v size object - * @param {number} dpi DPI - * @returns {{ width: number, height: number }} adjusted size object - */ -const adjustDpi = (v, dpi) => ({ - width: v.width ? v.width * dpi : v.width, - height: v.height ? v.height * dpi : v.height, -}); - /** * Returns size object from a given string * @@ -108,7 +96,6 @@ const getNumberSize = (n) => toSizeObject([n]); */ const getSize = (page) => { const value = page.props?.size || 'A4'; - const dpi = parseFloat(page.props?.dpi || 72); const type = typeof value; @@ -127,8 +114,6 @@ const getSize = (page) => { size = value; } - size = adjustDpi(size, dpi / 72); - return isLandscape(page) ? flipSizeObject(size) : size; }; diff --git a/packages/layout/src/steps/resolveStyles.js b/packages/layout/src/steps/resolveStyles.js index 1c24b3c8d..b94637432 100644 --- a/packages/layout/src/steps/resolveStyles.js +++ b/packages/layout/src/steps/resolveStyles.js @@ -56,7 +56,7 @@ const resolveNodeStyles = (container) => (node) => { * @returns {Object} document page with resolved styles */ export const resolvePageStyles = (page) => { - const dpi = page.props?.dpi || 72; + const dpi = 72; // Removed: page.props?.dpi || 72; const width = page.box?.width || page.style.width; const height = page.box?.height || page.style.height; const orientation = page.props?.orientation || 'portrait'; diff --git a/packages/stylesheet/src/transform/units.js b/packages/stylesheet/src/transform/units.js index c4f18fe96..01ec54b2e 100644 --- a/packages/stylesheet/src/transform/units.js +++ b/packages/stylesheet/src/transform/units.js @@ -22,7 +22,7 @@ const parseValue = (value) => { const transformUnit = (container, value) => { const scalar = parseValue(value); - const dpi = container.dpi || 72; + const dpi = 72; // Removed: container.dpi || 72 const mmFactor = (1 / 25.4) * dpi; const cmFactor = (1 / 2.54) * dpi; From f5b8ecab944359678885c58889945cb35e749f27 Mon Sep 17 00:00:00 2001 From: Nikischin Date: Sun, 2 Jun 2024 14:34:45 +0200 Subject: [PATCH 2/3] Allow to pass pixel sizes --- .changeset/pretty-jars-begin.md | 9 +++++++++ packages/layout/src/page/getSize.js | 16 ++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 .changeset/pretty-jars-begin.md diff --git a/.changeset/pretty-jars-begin.md b/.changeset/pretty-jars-begin.md new file mode 100644 index 000000000..aa5edf5c6 --- /dev/null +++ b/.changeset/pretty-jars-begin.md @@ -0,0 +1,9 @@ +--- +'@react-pdf/layout': minor +'@react-pdf/pdfkit': minor +'@react-pdf/render': minor +'@react-pdf/stylesheet': minor +'@react-pdf/types': minor +--- + +fix: fix dpi \ No newline at end of file diff --git a/packages/layout/src/page/getSize.js b/packages/layout/src/page/getSize.js index 6db1191a5..4fe676a2d 100644 --- a/packages/layout/src/page/getSize.js +++ b/packages/layout/src/page/getSize.js @@ -70,6 +70,18 @@ const toSizeObject = (v) => ({ width: v[0], height: v[1] }); */ const flipSizeObject = (v) => ({ width: v.height, height: v.width }); +/** + * Adjust page size to passed DPI + * + * @param {{ width: number, height: number }} v size object + * @param {number} dpi DPI + * @returns {{ width: number, height: number }} adjusted size object + */ +const adjustDpi = (v, dpi) => ({ + width: v.width ? v.width * (72 / dpi) : v.width, + height: v.height ? v.height * (72 / dpi) : v.height, +}); + /** * Returns size object from a given string * @@ -96,6 +108,7 @@ const getNumberSize = (n) => toSizeObject([n]); */ const getSize = (page) => { const value = page.props?.size || 'A4'; + const dpi = parseFloat(page.props?.dpi || 72); const type = typeof value; @@ -108,10 +121,13 @@ const getSize = (page) => { size = getStringSize(value); } else if (Array.isArray(value)) { size = toSizeObject(value); + size = adjustDpi(size, dpi); } else if (type === 'number') { size = getNumberSize(value); + size = adjustDpi(size, dpi); } else { size = value; + size = adjustDpi(size, dpi); } return isLandscape(page) ? flipSizeObject(size) : size; From 5b9608ab7abf0f757ade5c69c295267ab8066b00 Mon Sep 17 00:00:00 2001 From: Nikischin Date: Mon, 3 Jun 2024 13:53:58 +0200 Subject: [PATCH 3/3] Allow units for page size --- packages/layout/src/page/getSize.js | 78 ++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/packages/layout/src/page/getSize.js b/packages/layout/src/page/getSize.js index 4fe676a2d..39b84a83a 100644 --- a/packages/layout/src/page/getSize.js +++ b/packages/layout/src/page/getSize.js @@ -1,5 +1,6 @@ import isLandscape from './isLandscape'; +// page sizes for 72dpi. 72dpi is used internally by pdfkit const PAGE_SIZES = { '4A0': [4767.87, 6740.79], '2A0': [3370.39, 4767.87], @@ -54,11 +55,56 @@ const PAGE_SIZES = { ID1: [153, 243], }; +/** + * Parses scalar value in value and unit pairs + * + * @param {string} value scalar value + * @returns {Object} parsed value + */ +const parseValue = (value) => { + const match = /^(-?\d*\.?\d+)(in|mm|cm|pt|px)?$/g.exec(value); + + return match + ? { value: parseFloat(match[1]), unit: match[2] || 'pt' } + : { value, unit: undefined }; +}; + +/** + * Transform given scalar value to 72dpi equivalent of size + * + * @param {string} value styles value + * @param {number} inputDpi user defined dpi + * @returns {Object} transformed value + */ +const transformUnit = (value, inputDpi) => { + const scalar = parseValue(value); + + const outputDpi = 72; + const mmFactor = (1 / 25.4) * outputDpi; + const cmFactor = (1 / 2.54) * outputDpi; + + switch (scalar.unit) { + case 'in': + return scalar.value * outputDpi; + case 'mm': + return scalar.value * mmFactor; + case 'cm': + return scalar.value * cmFactor; + default: + return scalar.value * (outputDpi / inputDpi); + } +}; + +const transformUnits = ({ width, height }, dpi) => ({ + width: transformUnit(width, dpi), + height: transformUnit(height, dpi), +}); + /** * Transforms array into size object * - * @param {number[]} v array - * @returns {{ width: number, height: number }} size object with width and height + * @param {number[] | string[]} v array + * @returns {{ width: number | string, height: number | string }} size object with width and height */ const toSizeObject = (v) => ({ width: v[0], height: v[1] }); @@ -70,18 +116,6 @@ const toSizeObject = (v) => ({ width: v[0], height: v[1] }); */ const flipSizeObject = (v) => ({ width: v.height, height: v.width }); -/** - * Adjust page size to passed DPI - * - * @param {{ width: number, height: number }} v size object - * @param {number} dpi DPI - * @returns {{ width: number, height: number }} adjusted size object - */ -const adjustDpi = (v, dpi) => ({ - width: v.width ? v.width * (72 / dpi) : v.width, - height: v.height ? v.height * (72 / dpi) : v.height, -}); - /** * Returns size object from a given string * @@ -95,10 +129,10 @@ const getStringSize = (v) => { /** * Returns size object from a single number * - * @param {number} n page size number - * @returns {{ width: number, height: number }} size object with width and height + * @param {number|string} n page size number + * @returns {{ width: number|string, height: number|string }} size object with width and height */ -const getNumberSize = (n) => toSizeObject([n]); +const getNumberSize = (n) => toSizeObject([n, n]); /** * Return page size in an object { width, height } @@ -116,18 +150,14 @@ const getSize = (page) => { * @type {{ width: number, height: number }} */ let size; - if (type === 'string') { size = getStringSize(value); } else if (Array.isArray(value)) { - size = toSizeObject(value); - size = adjustDpi(size, dpi); + size = transformUnits(toSizeObject(value), dpi); } else if (type === 'number') { - size = getNumberSize(value); - size = adjustDpi(size, dpi); + size = transformUnits(getNumberSize(value), dpi); } else { - size = value; - size = adjustDpi(size, dpi); + size = transformUnits(value, dpi); } return isLandscape(page) ? flipSizeObject(size) : size;