ings.marginLeft = cmToInches(settings.margin.left); printSettings.marginRight = cmToInches(settings.margin.right); printSettings.marginTop = cmToInches(settings.margin.top); printSettings.printBGColors = settings.background; printSettings.printBGImages = settings.background; printSettings.scaling = settings.scale; printSettings.shrinkToFit = settings.shrinkToFit; printSettings.headerStrCenter = ""; printSettings.headerStrLeft = ""; printSettings.headerStrRight = ""; printSettings.footerStrCenter = ""; printSettings.footerStrLeft = ""; printSettings.footerStrRight = ""; // Override any os-specific unwriteable margins printSettings.unwriteableMarginTop = 0; printSettings.unwriteableMarginLeft = 0; printSettings.unwriteableMarginBottom = 0; printSettings.unwriteableMarginRight = 0; if (settings.orientation === "landscape") { printSettings.orientation = Ci.nsIPrintSettings.kLandscapeOrientation; } if (settings.pageRanges?.length) { printSettings.pageRanges = parseRanges(settings.pageRanges); } return printSettings; }; /** * Convert array of strings of the form ["1-3", "2-4", "7", "9-"] to an flat array of * limits, like [1, 4, 7, 7, 9, 2**31 - 1] (meaning 1-4, 7, 9-end) * * @param {Array.} ranges * Page ranges to print, e.g., ['1-5', '8', '11-13']. * Defaults to the empty string, which means print all pages. * * @returns {Array.} * Even-length array containing page range limits */ function parseRanges(ranges) { const MAX_PAGES = 0x7fffffff; if (ranges.length === 0) { return []; } let allLimits = []; for (let range of ranges) { let limits; if (typeof range !== "string") { // We got a single integer so the limits are just that page lazy.assert.positiveInteger( range, lazy.pprint`Expected "range" to be a string or a positive integer, got ${range}` ); limits = [range, range]; } else { // We got a string presumably of the form | ? "-" ? const msg = lazy.pprint`Expected "range" to be of the form or -, got ${range}`; limits = range.split("-").map(x => x.trim()); lazy.assert.that(o => [1, 2].includes(o.length), msg)(limits); // Single numbers map to a range with that page at the start and the end if (limits.length == 1) { limits.push(limits[0]); } // Need to check that both limits are strings consisting only of // decimal digits (or empty strings) const assertNumeric = lazy.assert.that(o => /^\d*$/.test(o), msg); limits.every(x => assertNumeric(x)); // Convert from strings representing numbers to actual numbers // If we don't have an upper bound, choose something very large; // the print code will later truncate this to the number of pages limits = limits.map((limitStr, i) => { if (limitStr == "") { return i == 0 ? 1 : MAX_PAGES; } return parseInt(limitStr); }); } lazy.assert.that( x => x[0] <= x[1], lazy.pprint`Expected "range" lower limit to be less than the upper limit, got ${range}` )(limits); allLimits.push(limits); } // Order by lower limit allLimits.sort((a, b) => a[0] - b[0]); let parsedRanges = [allLimits.shift()]; for (let limits of allLimits) { let prev = parsedRanges[parsedRanges.length - 1]; let prevMax = prev[1]; let [min, max] = limits; if (min <= prevMax) { // min is inside previous range, so extend the max if needed if (max > prevMax) { prev[1] = max; } } else { // Otherwise we have a new range parsedRanges.push(limits); } } let rv = parsedRanges.flat(); lazy.logger.debug(`Got page ranges [${rv.join(", ")}]`); return rv; } print.printToBinaryString = async function (browsingContext, printSettings) { // Create a stream to write to. const stream = Cc["@mozilla.org/storagestream;1"].createInstance( Ci.nsIStorageStream ); stream.init(4096, 0xffffffff); printSettings.outputDestination = Ci.nsIPrintSettings.kOutputDestinationStream; printSettings.outputStream = stream.getOutputStream(0); await browsingContext.print(printSettings); const inputStream = Cc["@mozilla.org/binaryinputstream;1"].createInstance( Ci.nsIBinaryInputStream ); inputStream.setInputStream(stream.newInputStream(0)); const available = inputStream.available(); const bytes = inputStream.readBytes(available); stream.close(); return bytes; }; PK