Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow spool limits for pdf prints #728

Merged
merged 7 commits into from
Nov 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions js/qz-tray.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use strict';

/**
* @version 2.1.2
* @version 2.1.2+11
* @overview QZ Tray Connector
* <p/>
* Connects a web client to the QZ Tray software.
Expand Down Expand Up @@ -38,7 +38,7 @@ var qz = (function() {
///// PRIVATE METHODS /////

var _qz = {
VERSION: "2.1.2", //must match @version above
VERSION: "2.1.2+11", //must match @version above
DEBUG: false,

log: {
Expand Down Expand Up @@ -451,8 +451,7 @@ var qz = (function() {

altPrinting: false,
encoding: null,
endOfDoc: null,
perSpool: 1
spool: null
}
},

Expand Down Expand Up @@ -767,7 +766,19 @@ var qz = (function() {
config.rasterize = true;
}
}

if(_qz.tools.versionCompare(2, 1, 2, 11) < 0) {
if(config.spool) {
if(config.spool.size) {
config.perSpool = config.spool.size;
delete config.spool.size;
}
if(config.spool.end) {
config.endOfDoc = config.spool.end;
delete config.spool.end;
}
delete config.spool;
}
}
return config;
},

Expand Down Expand Up @@ -1305,8 +1316,11 @@ var qz = (function() {
*
* @param {boolean} [options.altPrinting=false] Print the specified file using CUPS command line arguments. Has no effect on Windows.
* @param {string} [options.encoding=null] Character set
* @param {string} [options.endOfDoc=null]
* @param {number} [options.perSpool=1] Number of pages per spool.
* @param {string} [options.endOfDoc=null] DEPRECATED Raw only: Character(s) denoting end of a page to control spooling.
* @param {number} [options.perSpool=1] DEPRECATED: Raw only: Number of pages per spool.
* @param {Object} [options.spool=null] Advanced spooling options.
* @param {number} [options.spool.size=null] Number of pages per spool. Default is no limit. If <code>spool.end</code> is provided, defaults to <code>1</code>
* @param {string} [options.spool.end=null] Raw only: Character(s) denoting end of a page to control spooling.
*
* @memberof qz.configs
*/
Expand Down
20 changes: 14 additions & 6 deletions sample.html
Original file line number Diff line number Diff line change
Expand Up @@ -219,8 +219,8 @@ <h3>Raw Printing</h3>
</div>

<div class="form-group form-inline">
<label for="rawEndOfDoc">End Of Doc</label>
<input type="text" id="rawEndOfDoc" class="form-control pull-right" />
<label for="rawSpoolEnd">End Of Doc</label>
<input type="text" id="rawSpoolEnd" class="form-control pull-right" />
</div>

<div class="form-group form-inline">
Expand Down Expand Up @@ -414,6 +414,11 @@ <h3>Pixel Printing</h3>
<label for="pxlRotation">Rotation</label>
<input type="number" step="any" id="pxlRotation" class="form-control pull-right" />
</div>

<div class="form-group form-inline">
<label for="pxlSpoolSize">Per Spool</label>
<input type="number" id="pxlSpoolSize" class="form-control pull-right" />
</div>
</div>
<div class="col-md-6">
<div class="form-group">
Expand Down Expand Up @@ -2273,9 +2278,9 @@ <h4 class="panel-title">Options</h4>
/// Resets ///
function resetRawOptions() {
//config
$("#rawPerSpool").val(1);
$("#rawSpoolSize").val(1);
$("#rawEncoding").val(null);
$("#rawEndOfDoc").val(null);
$("#rawSpoolEnd").val(null);
$("#rawAltPrinting").prop('checked', false);
$("#rawCopies").val(1);

Expand All @@ -2302,6 +2307,7 @@ <h4 class="panel-title">Options</h4>
$("#pxlPrinterTray").val(null);
$("#pxlRasterize").prop('checked', false);
$("#pxlRotation").val(0);
$("#pxlSpoolSize").val("");
$("#pxlScale").prop('checked', true);
$("#pxlUnitsIN").prop('checked', true);

Expand Down Expand Up @@ -2825,20 +2831,22 @@ <h4 class="panel-title">Options</h4>
}

var copies = 1;
var spoolSize = null;
var jobName = null;
if ($("#rawTab").hasClass("active")) {
copies = includedValue($("#rawCopies"));
spoolSize = includedValue($("#rawSpoolSize"));
jobName = includedValue($("#rawJobName"));
} else {
copies = includedValue($("#pxlCopies"));
spoolSize = includedValue($("#pxlSpoolSize"));
jobName = includedValue($("#pxlJobName"));
}

cfg.reconfigure({
altPrinting: includedValue($("#rawAltPrinting"), isChecked($("#rawAltPrinting"), cleanConditions['rawAltPrinting'])),
encoding: includedValue($("#rawEncoding")),
endOfDoc: includedValue($("#rawEndOfDoc")),
perSpool: includedValue($("#rawPerSpool")),
spool: { size: spoolSize, end: includedValue($("#rawSpoolEnd")) },

bounds: pxlBounds,
colorType: includedValue($("#pxlColorType")),
Expand Down
68 changes: 43 additions & 25 deletions src/qz/printer/BookBundle.java
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
package qz.printer;

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import qz.utils.SystemUtilities;

import javax.print.attribute.standard.OrientationRequested;
import java.awt.*;
import java.awt.print.Book;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.util.ArrayList;
import java.util.List;

/**
* Wrapper of the {@code Book} class as a {@code Printable} type,
* since PrinterJob implementations do not seem to handle the {@code Pageable} interface properly.
*/
public class BookBundle extends Book implements Printable {
public class BookBundle extends Book {

private static final Logger log = LoggerFactory.getLogger(BookBundle.class);

Expand All @@ -30,33 +24,57 @@ public BookBundle() {
super();
}

@Override
public int print(Graphics g, PageFormat format, int pageIndex) throws PrinterException {
log.trace("Requested page {} for printing", pageIndex);

if (pageIndex < getNumberOfPages()) {
Printable printable = getPrintable(pageIndex);
if (printable != lastPrint) {
lastPrint = printable;
lastStarted = pageIndex;
}

return printable.print(g, format, pageIndex - lastStarted);
}

return NO_SUCH_PAGE;
}

/**
* Wrapper of the wrapper class so that PrinterJob implementations will handle it as proper pageable
*/
public Book wrapAndPresent() {
Book cover = new Book();
for(int i = 0; i < getNumberOfPages(); i++) {
cover.append(this, getPageFormat(i));
cover.append(new PrintingPress(), getPageFormat(i));
}

return cover;
}

public Book wrapAndPresent(int offset, int length) {
Book coverSubset = new Book();
for(int i = offset; i < offset + length && i < getNumberOfPages(); i++) {
coverSubset.append(new PrintingPress(offset), getPageFormat(i));
}

return coverSubset;
}


/** Printable wrapper to ensure proper reading of multiple documents across spooling */
private class PrintingPress implements Printable {
private int pageOffset;

public PrintingPress() {
this(0);
}

public PrintingPress(int offset) {
pageOffset = offset;
}

@Override
public int print(Graphics g, PageFormat format, int pageIndex) throws PrinterException {
pageIndex += pageOffset;
log.trace("Requested page {} for printing", pageIndex);

if (pageIndex < getNumberOfPages()) {
Printable printable = getPrintable(pageIndex);
if (printable != lastPrint) {
lastPrint = printable;
lastStarted = pageIndex;
}

return printable.print(g, format, pageIndex - lastStarted);
}

return NO_SUCH_PAGE;
}
}

}
58 changes: 46 additions & 12 deletions src/qz/printer/PrintOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,30 @@ public PrintOptions(JSONObject configOpts, PrintOutput output, PrintingUtilities
if (!configOpts.isNull("encoding")) {
rawOptions.encoding = configOpts.optString("encoding", null);
}
if (!configOpts.isNull("endOfDoc")) {
rawOptions.endOfDoc = configOpts.optString("endOfDoc", null);
}
if (!configOpts.isNull("perSpool")) {
try { rawOptions.perSpool = configOpts.getInt("perSpool"); }
catch(JSONException e) { LoggerUtilities.optionWarn(log, "integer", "perSpool", configOpts.opt("perSpool")); }
if (!configOpts.isNull("spool")) {
JSONObject spool = configOpts.optJSONObject("spool");
if (spool != null) {
if (!spool.isNull("size")) {
try { rawOptions.spoolSize = spool.getInt("size"); }
catch(JSONException e) { LoggerUtilities.optionWarn(log, "integer", "spool.size", spool.opt("size")); }
}
// TODO: Implement spool.start
if (!spool.isNull("end")) {
rawOptions.spoolEnd = spool.optString("end");
}

} else {
LoggerUtilities.optionWarn(log, "JSONObject", "spool", configOpts.opt("spool"));
}
} else {
// Deprecated
if (!configOpts.isNull("perSpool")) {
try { rawOptions.spoolSize = configOpts.getInt("perSpool"); }
catch(JSONException e) { LoggerUtilities.optionWarn(log, "integer", "perSpool", configOpts.opt("perSpool")); }
}
if (!configOpts.isNull("endOfDoc")) {
rawOptions.spoolEnd = configOpts.optString("endOfDoc", null);
}
}
if (!configOpts.isNull("copies")) {
try { rawOptions.copies = configOpts.getInt("copies"); }
Expand Down Expand Up @@ -272,6 +290,17 @@ public PrintOptions(JSONObject configOpts, PrintOutput output, PrintingUtilities
try { psOptions.paperThickness = configOpts.getDouble("paperThickness"); }
catch(JSONException e) { LoggerUtilities.optionWarn(log, "double", "paperThickness", configOpts.opt("paperThickness")); }
}
if (!configOpts.isNull("spool")) {
JSONObject spool = configOpts.optJSONObject("spool");
if (spool != null) {
if (!spool.isNull("size")) {
try { psOptions.spoolSize = spool.getInt("size"); }
catch(JSONException e) { LoggerUtilities.optionWarn(log, "integer", "spool.size", spool.opt("size")); }
}
} else {
LoggerUtilities.optionWarn(log, "JSONObject", "spool", configOpts.opt("spool"));
}
}
if (!configOpts.isNull("printerTray")) {
psOptions.printerTray = configOpts.optString("printerTray", null);
}
Expand Down Expand Up @@ -358,8 +387,8 @@ public Pixel getPixelOptions() {
public class Raw {
private boolean altPrinting = false; //Alternate printing for linux systems
private String encoding = null; //Text encoding / charset
private String endOfDoc = null; //End of document character
private int perSpool = 1; //Pages per spool
private String spoolEnd = null; //End of document character(s)
private int spoolSize = 1; //Pages per spool
private int copies = 1; //Job copies
private String jobName = null; //Job name

Expand All @@ -372,12 +401,12 @@ public String getEncoding() {
return encoding;
}

public String getEndOfDoc() {
return endOfDoc;
public String getSpoolEnd() {
return spoolEnd;
}

public int getPerSpool() {
return perSpool;
public int getSpoolSize() {
return spoolSize;
}

public int getCopies() {
Expand All @@ -404,6 +433,7 @@ public class Pixel {
private Margins margins = new Margins(); //Page margins
private Orientation orientation = null; //Page orientation
private double paperThickness = -1; //Paper thickness
private int spoolSize = 0; //Pages before sending to printer
private String printerTray = null; //Printer tray to use
private boolean rasterize = true; //Whether documents are rasterized before printing
private double rotation = 0; //Image rotation
Expand Down Expand Up @@ -464,6 +494,10 @@ public double getPaperThickness() {
return paperThickness;
}

public int getSpoolSize() {
return spoolSize;
}

public String getPrinterTray() {
return printerTray;
}
Expand Down
19 changes: 16 additions & 3 deletions src/qz/printer/action/PrintPDF.java
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,23 @@ public void print(PrintOutput output, PrintOptions options) throws PrinterExcept
bundle.append(new PDFWrapper(doc, scale, false, (float)(useDensity * pxlOpts.getUnits().as1Inch()), false, pxlOpts.getOrientation(), hints), page, doc.getNumberOfPages());
}

job.setJobName(pxlOpts.getJobName(Constants.PDF_PRINT));
job.setPageable(bundle.wrapAndPresent());
if (pxlOpts.getSpoolSize() > 0 && bundle.getNumberOfPages() > pxlOpts.getSpoolSize()) {
int jobNum = 1;
int offset = 0;
while(offset < bundle.getNumberOfPages()) {
job.setJobName(pxlOpts.getJobName(Constants.PDF_PRINT) + "-" + jobNum++);
job.setPageable(bundle.wrapAndPresent(offset, pxlOpts.getSpoolSize()));

printCopies(output, pxlOpts, job, attributes);
printCopies(output, pxlOpts, job, attributes);

offset += pxlOpts.getSpoolSize();
}
} else {
job.setJobName(pxlOpts.getJobName(Constants.PDF_PRINT));
job.setPageable(bundle.wrapAndPresent());

printCopies(output, pxlOpts, job, attributes);
}
}

private void rotatePage(PDDocument doc, PDPage page, double rotation) {
Expand Down
4 changes: 2 additions & 2 deletions src/qz/printer/action/PrintRaw.java
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,9 @@ public void print(PrintOutput output, PrintOptions options) throws PrintExceptio
PrintOptions.Raw rawOpts = options.getRawOptions();

List<ByteArrayBuilder> pages;
if (rawOpts.getPerSpool() > 0 && rawOpts.getEndOfDoc() != null && !rawOpts.getEndOfDoc().isEmpty()) {
if (rawOpts.getSpoolSize() > 0 && rawOpts.getSpoolEnd() != null && !rawOpts.getSpoolEnd().isEmpty()) {
try {
pages = ByteUtilities.splitByteArray(commands.getByteArray(), rawOpts.getEndOfDoc().getBytes(encoding), rawOpts.getPerSpool());
pages = ByteUtilities.splitByteArray(commands.getByteArray(), rawOpts.getSpoolEnd().getBytes(encoding), rawOpts.getSpoolSize());
}
catch(UnsupportedEncodingException e) {
throw new PrintException(e);
Expand Down