Skip to content

Commit

Permalink
Raw HTML density support (qzind#676)
Browse files Browse the repository at this point in the history
Various raw HTML fixes
- Uses density defaults closer to expected raw usage
- Address issue with zoom allowance on large captures
- Allow raw prints to use Pixel density
- Further improvements to calcZoom method + fallback to 1x zoom on failures

Co-authored-by: Berenz <[email protected]>
  • Loading branch information
tresf and Berenz authored Jul 10, 2020
1 parent 2644b22 commit 3db7eed
Show file tree
Hide file tree
Showing 8 changed files with 122 additions and 82 deletions.
2 changes: 1 addition & 1 deletion js/qz-tray.js
Original file line number Diff line number Diff line change
Expand Up @@ -1269,7 +1269,7 @@ var qz = (function() {
*
* @param {Object} options Default options used by printer configs if not overridden.
*
* @param {Object} [option.bounds=null] Bounding box rectangle.
* @param {Object} [options.bounds=null] Bounding box rectangle.
* @param {number} [options.bounds.x=0] Distance from left for bounding box starting corner
* @param {number} [options.bounds.y=0] Distance from top for bounding box starting corner
* @param {number} [options.bounds.width=0] Width of bounding box
Expand Down
23 changes: 15 additions & 8 deletions src/qz/printer/LanguageType.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,29 +20,31 @@
*/
public enum LanguageType {

ZPL(false, true, "ZPL", "ZPL2", "ZPLII", "ZEBRA"),
EPL(true, true, "EPL", "EPL2", "EPLII"),
CPCL(false, true),
ESCP(false, false, "ESCP", "ESCP2", "ESCPOS", "ESC", "ESC/P", "ESC/P2", "ESCP/P2", "ESC/POS", "ESC\\P", "EPSON"),
EVOLIS(false, false),
UNKNOWN(false, false);
ZPL(false, true, 203, "ZPL", "ZPL2", "ZPLII", "ZEBRA"),
EPL(true, true, 203, "EPL", "EPL2", "EPLII"),
CPCL(false, true, 203),
ESCP(false, false, 180, "ESCP", "ESCP2", "ESCPOS", "ESC", "ESC/P", "ESC/P2", "ESCP/P2", "ESC/POS", "ESC\\P", "EPSON"),
EVOLIS(false, false, 300),
UNKNOWN(false, false, 72);


private boolean imgOutputInvert = false;
private boolean imgWidthValidated = false;
private double defaultDensity = 72;
private List<String> altNames;

LanguageType(boolean imgOutputInvert, boolean imgWidthValidated, String... altNames) {
LanguageType(boolean imgOutputInvert, boolean imgWidthValidated, double defaultDensity, String... altNames) {
this.imgOutputInvert = imgOutputInvert;
this.imgWidthValidated = imgWidthValidated;
this.defaultDensity = defaultDensity;

this.altNames = new ArrayList<>();
Collections.addAll(this.altNames, altNames);
}

public static LanguageType getType(String type) {
for(LanguageType lang : LanguageType.values()) {
if (type.equalsIgnoreCase(lang.name()) || lang.altNames.contains(type)) {
if (lang.name().equalsIgnoreCase(type) || lang.altNames.contains(type)) {
return lang;
}
}
Expand Down Expand Up @@ -72,4 +74,9 @@ public boolean requiresImageOutputInverted() {
public boolean requiresImageWidthValidated() {
return imgWidthValidated;
}

public double getDefaultDensity() {
return defaultDensity;
}

}
12 changes: 2 additions & 10 deletions src/qz/printer/PrintOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,6 @@ public PrintOptions(JSONObject configOpts, PrintOutput output, PrintingUtilities
if (!configOpts.isNull("endOfDoc")) {
rawOptions.endOfDoc = configOpts.optString("endOfDoc", null);
}
if (!configOpts.isNull("language")) {
rawOptions.language = configOpts.optString("language", null);
}
if (!configOpts.isNull("perSpool")) {
try { rawOptions.perSpool = configOpts.getInt("perSpool"); }
catch(JSONException e) { LoggerUtilities.optionWarn(log, "integer", "perSpool", configOpts.opt("perSpool")); }
Expand Down Expand Up @@ -160,7 +157,7 @@ public PrintOptions(JSONObject configOpts, PrintOutput output, PrintingUtilities
bestRes = pr;
}
}
if(bestRes != null) {
if (bestRes != null) {
psOptions.density = bestRes.getFeedResolution(psOptions.units.resSyntax);
psOptions.crossDensity = bestRes.getCrossFeedResolution(psOptions.units.resSyntax);
} else {
Expand All @@ -173,7 +170,7 @@ public PrintOptions(JSONObject configOpts, PrintOutput output, PrintingUtilities
lowestRes = pr;
}
}
if(lowestRes != null) {
if (lowestRes != null) {
psOptions.density = lowestRes.getFeedResolution(psOptions.units.resSyntax);
psOptions.crossDensity = lowestRes.getCrossFeedResolution(psOptions.units.resSyntax);
} else {
Expand Down Expand Up @@ -362,7 +359,6 @@ 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 String language = null; //Printer language
private int perSpool = 1; //Pages per spool
private int copies = 1; //Job copies
private String jobName = null; //Job name
Expand All @@ -380,10 +376,6 @@ public String getEndOfDoc() {
return endOfDoc;
}

public String getLanguage() {
return language;
}

public int getPerSpool() {
return perSpool;
}
Expand Down
18 changes: 15 additions & 3 deletions src/qz/printer/action/PrintHTML.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,10 +112,10 @@ public void parseData(JSONArray printData, PrintOptions options) throws JSONExce
JSONObject dataOpt = data.getJSONObject("options");

if (!dataOpt.isNull("pageWidth") && dataOpt.optDouble("pageWidth") > 0) {
pageWidth = dataOpt.optDouble("pageWidth") * (72.0 / pxlOpts.getUnits().as1Inch());
pageWidth = dataOpt.optDouble("pageWidth") * convertFactor;
}
if (!dataOpt.isNull("pageHeight") && dataOpt.optDouble("pageHeight") > 0) {
pageHeight = dataOpt.optDouble("pageHeight") * (72.0 / pxlOpts.getUnits().as1Inch());
pageHeight = dataOpt.optDouble("pageHeight") * convertFactor;
}
}

Expand All @@ -141,7 +141,19 @@ public void print(PrintOutput output, PrintOptions options) throws PrinterExcept
for(WebAppModel model : models) {
try { images.add(WebApp.raster(model)); }
catch(Throwable t) {
throw new PrinterException(t.getMessage());
if (model.getZoom() > 1 && t instanceof IllegalArgumentException) {
//probably a unrecognized image loader error, try at default zoom
try {
log.warn("Capture failed with increased zoom, attempting with default value");
model.setZoom(1);
images.add(WebApp.raster(model));
}
catch(Throwable tt) {
throw new PrinterException(tt.getMessage());
}
} else {
throw new PrinterException(t.getMessage());
}
}
}

Expand Down
42 changes: 36 additions & 6 deletions src/qz/printer/action/PrintRaw.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import javax.print.attribute.standard.JobName;
import javax.print.event.PrintJobEvent;
import javax.print.event.PrintJobListener;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.Socket;
Expand Down Expand Up @@ -108,7 +109,7 @@ public void parseData(JSONArray printData, PrintOptions options) throws JSONExce
try {
switch(format) {
case HTML:
commands.append(getHtmlWrapper(cmd, opt, flavor != PrintingUtilities.Flavor.PLAIN).getImageCommand(opt));
commands.append(getHtmlWrapper(cmd, opt, flavor != PrintingUtilities.Flavor.PLAIN, options.getPixelOptions()).getImageCommand(opt));
break;
case IMAGE:
commands.append(getImageWrapper(cmd, opt, flavor != PrintingUtilities.Flavor.BASE64).getImageCommand(opt));
Expand Down Expand Up @@ -187,18 +188,47 @@ private ImageWrapper getPdfWrapper(String data, JSONObject opt, boolean fromFile
return getWrapper(bi, opt);
}

private ImageWrapper getHtmlWrapper(String data, JSONObject opt, boolean fromFile) throws IOException {
private ImageWrapper getHtmlWrapper(String data, JSONObject opt, boolean fromFile, PrintOptions.Pixel pxlOpts) throws IOException {
double density = (pxlOpts.getDensity() * pxlOpts.getUnits().as1Inch());
if (density <= 1) {
density = LanguageType.getType(opt.optString("language")).getDefaultDensity();
}
double pageZoom = density / 72.0;

double pageWidth = opt.optInt("pageWidth") / density * 72;
double pageHeight = opt.optInt("pageHeight") / density * 72;

BufferedImage bi;
WebAppModel model = new WebAppModel(data, !fromFile, pageWidth, pageHeight, false, pageZoom);

try {
WebApp.initialize(); //starts if not already started

WebAppModel model = new WebAppModel(data, !fromFile, opt.optInt("pageWidth"), opt.optInt("pageHeight"), false, opt.optDouble("zoom"));
bi = WebApp.raster(model);

// down scale back from web density
double scaleFactor = opt.optDouble("pageWidth", 0) / bi.getWidth();
BufferedImage scaled = new BufferedImage((int)(bi.getWidth() * scaleFactor), (int)(bi.getHeight() * scaleFactor), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = scaled.createGraphics();
g2d.drawImage(bi, 0, 0, (int)(bi.getWidth() * scaleFactor), (int)(bi.getHeight() * scaleFactor), null);
g2d.dispose();
bi = scaled;
}
catch(Throwable t) {
log.error("Failed to capture html raster");
throw new IOException(t);
if (model.getZoom() > 1 && t instanceof IllegalArgumentException) {
//probably a unrecognized image loader error, try at default zoom
try {
log.warn("Capture failed with increased zoom, attempting with default value");
model.setZoom(1);
bi = WebApp.raster(model);
}
catch(Throwable tt) {
log.error("Failed to capture html raster");
throw new IOException(tt);
}
} else {
log.error("Failed to capture html raster");
throw new IOException(t);
}
}

return getWrapper(bi, opt);
Expand Down
25 changes: 13 additions & 12 deletions src/qz/printer/action/WebApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,6 @@ public class WebApp extends Application {
base.getAttributes().setNamedItem(applied);
}

// find and set page zoom for increased quality
double usableZoom = calculateSupportedZoom(pageWidth, pageHeight);
if (usableZoom < pageZoom) {
log.warn("Zoom level {} decreased to {} due to physical memory limitations", pageZoom, usableZoom);
pageZoom = usableZoom;
}
webView.setZoom(pageZoom);
log.trace("Zooming in by x{} for increased quality", pageZoom);

//width was resized earlier (for responsive html), then calculate the best fit height
// FIXME: Should only be needed when height is unknown but fixes blank vector prints
double fittedHeight = findHeight();
Expand All @@ -101,6 +92,15 @@ public class WebApp extends Application {
pageHeight = fittedHeight;
}

// find and set page zoom for increased quality
double usableZoom = calculateSupportedZoom(pageWidth, pageHeight);
if (usableZoom < pageZoom) {
log.warn("Zoom level {} decreased to {} due to physical memory limitations", pageZoom, usableZoom);
pageZoom = usableZoom;
}
webView.setZoom(pageZoom);
log.trace("Zooming in by x{} for increased quality", pageZoom);

adjustSize(pageWidth * pageZoom, pageHeight * pageZoom);

//need to check for height again as resizing can cause partial results
Expand Down Expand Up @@ -327,7 +327,6 @@ public void pulse() {
unlatch(null);
}
catch(Exception e) {
log.error("Caught during snapshot");
unlatch(e);
}
finally {
Expand Down Expand Up @@ -429,9 +428,11 @@ private static double calculateSupportedZoom(double width, double height) {
long memory = Runtime.getRuntime().maxMemory();
int allowance = (memory / 1048576L) > 1024? 3:2;
if (headless) { allowance--; }
long availSpace = (long)((memory << allowance) / 72d);
long availSpace = memory << allowance;

return Math.sqrt(availSpace / (width * height));
// Memory needed for print is roughly estimated as
// (width * height) [pixels needed] * (pageZoom * 72d) [print density used] * 3 [rgb channels]
return Math.sqrt(availSpace / ((width * height) * (pageZoom * 72d) * 3));
}

/**
Expand Down
12 changes: 3 additions & 9 deletions src/qz/printer/action/WebAppModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public WebAppModel(String source, boolean plainText, double width, double height
this.plainText = plainText;
this.width = width;
this.height = height;
this.webWidth = width * (96d/72d);
this.webWidth = width * (96d / 72d);
this.webHeight = height * (96d / 72d);
this.isScaled = isScaled;
this.zoom = zoom;
Expand Down Expand Up @@ -43,6 +43,7 @@ public double getWidth() {

public void setWidth(double width) {
this.width = width;
this.webWidth = width * (96d / 72d);
}

public double getHeight() {
Expand All @@ -51,24 +52,17 @@ public double getHeight() {

public void setHeight(double height) {
this.height = height;
this.webHeight = height * (96d / 72d);
}

public double getWebWidth() {
return webWidth;
}

public void setWebWidth(double webWidth) {
this.webWidth = webWidth;
}

public double getWebHeight() {
return webHeight;
}

public void setWebHeight(double webHeight) {
this.webHeight = webHeight;
}

public boolean isScaled() {
return isScaled;
}
Expand Down
Loading

0 comments on commit 3db7eed

Please sign in to comment.