Java A3 printing on Macs coming out at A4 scale - java

I have an odd problem that seems to be specific to Mac computers. I have a prog that prints the content of an AWT drawing surface to an A3 sheet of paper. On Linux and windows machines the output is OK. Printing from a Mac I get the same dialog with the same preset parameters, the printer prints on an A3 sheet of paper as expected, but for some reason the image is scaled to fit an A4 area. Below are the relevant sections of code:
public void print() {
PrinterJob printJob = PrinterJob.getPrinterJob();
PageFormat format = new PageFormat();
format.setOrientation(PageFormat.LANDSCAPE);
double margin = 18; // quarter inch
double m2 = margin * 2;
Paper paper = format.getPaper();
paper.setSize(16.54 * 72, 11.69 * 72); // A3 Landscape
paper.setImageableArea(margin, margin, paper.getWidth()-m2, paper.getHeight()-m2);
format.setPaper(paper);
printJob.setPrintable(this, format);
PrintRequestAttributeSet attributes = new HashPrintRequestAttributeSet();
attributes.add(MediaSizeName.ISO_A3);
attributes.add(OrientationRequested.LANDSCAPE);
attributes.add(new MediaPrintableArea((int)margin, (int)margin,
(int)(paper.getWidth()-m2), (int)(paper.getHeight()-m2),
MediaPrintableArea.INCH));
if(printJob.printDialog(attributes) ){
try {
printJob.print(attributes);
} catch(PrinterException pe) {
pe.printStackTrace();
}
}
}
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
if (pageIndex > 0) {
return(NO_SUCH_PAGE);
} else {
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
if(this.componentToBePrinted instanceof PlannerView){
setScale(g2d);
}
disableDoubleBuffering(componentToBePrinted);
componentToBePrinted.paint(g2d);
enableDoubleBuffering(componentToBePrinted);
return(PAGE_EXISTS);
}
}
public void setScale(Graphics2D g2d){
PlannerView planner = (PlannerView)this.componentToBePrinted;
planner.resetZoom();
double scale = 1.0 / planner.getRowLength();
scale *= 4.0;
g2d.scale(scale, scale);
}
Does anyone know what could be causing this?
Cheers.

Try calling
PageFormat newFormat =printJob.pageDialog(format);
before printing, the printer may modify the margins.
At least take a look in the debugger and see what it turns into.
Also note that the Macintosh native printing coordinate systems for landscape is inverted.
So maybe try it with REVERSE_LANDSCAPE instead of LANDSCAPE ( and it might be flipped, but may not get list in translation)

Deal with setImageableArea(), change the values and try. Also apply reverse_landscape for mac.
And set the A3 size: 1190 & 842 not decimal values.

Related

Apache PDFBox Renders Straight Line Crooked in PNG

I have a PDF that when I render it to a png it renders a line crooked, or rather with a step in it. This is the PDF and what it should look like: https://drive.google.com/file/d/1E-zucbreD7pVwWc3Z4MNe_lzsP6D9m49/view
Here is the full PNG rendering using PDFBox 2.0.13 and openjdk version 1.8.0_181:
And here is the specific portion of the PNG that has the step:
Excerpt of the page content stream:
q
1 0 0 1 35.761 450.003 cm
0 i
0.75 w
0 0 m
50.923 0 l
S
Q
q
1 0 0 1 86.139 450 cm
0 i
0.75 w
0 0 m
14.9 0 l
S
Q
("cm" is an affine transform, "m" a moveto, "l" a lineto). One can see that the two lines are slightly different, one at 450.003, the other one at 450.
Here's some code that simulates the error by replicating what PDFBox is doing:
BufferedImage bim = new BufferedImage(612, 792, BufferedImage.TYPE_INT_ARGB);
Graphics2D g = (Graphics2D) bim.getGraphics();
RenderingHints r = new RenderingHints(null);
r.put(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
r.put(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
r.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g.addRenderingHints(r);
g.translate(0, 792);
g.scale(1, -1);
g.setStroke(new BasicStroke(0.75f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10));
g.setColor(Color.black);
GeneralPath path = new GeneralPath();
path.moveTo(35.761f, 450.003f);
path.lineTo(35.761f + 50.923f, 450.003f);
g.draw(path);
path = new GeneralPath();
path.moveTo(86.139f, 450f);
path.lineTo(86.139f + 14.9f, 450f);
g.draw(path);
g.dispose();
ImageIO.write(bim, "png", new File("...."));
One can get rid of the error by commenting this line:
r.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
This could be done in the source code of PDFBox, or by passing the renderingHints in PDFRenderer.setRenderingHints(). However that one isn't available now, but will be available in 2.0.14 (see issue PDFBOX-4435, try a snapshot). And you can expect the rendering to be of poor quality by not having anti aliasing.
Update:
instead of removing the line mentioned above, add this one:
r.put(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
Source.

WPrinterJob.validatePaper() is changing original imageableArea of page when I click on properties button of Print dialog and after print it

I am printing Legal size paper, when I print it without open properties dialog then it is printing properly, but when I click on "Properties" button for confirm page type (no matter I am clicking on "OK" or "Cancel" then Paper imageableArea is become changed while job.print(attributeSet)
Dialog with Properties Button
Expected Height/Width:612/1008
Actual Height/Width:612/792 (setting in WPrinterJob.validatePaper())
Printing page with issue
Here is my code,
private void preparePageFormat(PageFormat pf)
{
Paper ppr = new Paper();
pf.setOrientation(PageFormat.LANDSCAPE);
MediaSizeName msn = MediaSizeName.NA_LEGAL;
MediaSize msz = MediaSize.getMediaSizeForName(msn);
double inch = 72.0;
width = msz.getX(MediaSize.INCH) * inch;
height = msz.getY(MediaSize.INCH) * inch;
ppr.setSize(a4Width, a4Height);
ppr.setImageableArea(0, 0, a4Width, a4Height);
pf.setPaper(ppr);
}
main()
{
PrinterJob job = PrinterJob.getPrinterJob();
PageFormat pageFormat = job.defaultPage();
preparePageFormat(pageFormat);
job.setPrintable(previewPanel.getPrintable(), pageFormat);
PrintRequestAttributeSet attributeSet = new HashPrintRequestAttributeSet();
attributeSet.add(OrientationRequested.LANDSCAPE);
attributeSet.add(MediaSizeName.NA_LEGAL);
if (job.printDialog(attributeSet))
{
attributeSet.add(new MediaPrintableArea((float)pageFormat.getImageableX(),(float)pageFormat.getImageableY(),
(float)pageFormat.getImageableWidth(),(float)pageFormat.getImageableHeight(),MediaPrintableArea.INCH));
job.print(attributeSet);
}
}
For this printer issue, you need to confirm setting from Printer Properties .
Verify all settings are matching with your Page Type.
And verfiy here too.

How can I optimize the weight of SVG images generated using Apache Batik?

I have written the following code using Apache Batik in order to generate SVG images (full source available on GitHub) representing badges showing if code passes a SonarQube quality gate or not:
private SVGGraphics2D generateFor(final QualityGateStatus status) {
// new SVG graphics
final SVGGraphics2D svgGraphics2D = new SVGGraphics2D(this.svgGeneratorContext, false);
// set SVG canvas size
svgGraphics2D.setSVGCanvasSize(new Dimension(LABEL_WIDTH + status.displayWidth(), CANVAS_HEIGHT));
// set font
svgGraphics2D.setFont(FONT_FAMILY);
// draw Label background
svgGraphics2D.setColor(COLOR_BACKGROUND_LABEL);
svgGraphics2D.fillRoundRect(0, 0, LABEL_WIDTH, CANVAS_HEIGHT, BACKGROUND_CORNER_ARC_DIAMETER, BACKGROUND_CORNER_ARC_DIAMETER);
svgGraphics2D.fillRect(LABEL_WIDTH - BACKGROUND_CORNER_ARC_DIAMETER, 0, BACKGROUND_CORNER_ARC_DIAMETER, CANVAS_HEIGHT);
// draw Label text shadow
svgGraphics2D.setColor(COLOR_SHADOW);
svgGraphics2D.drawString(LABEL_TEXT, X_MARGIN, Y_OFFSET_SHADOW);
// draw Label text
svgGraphics2D.setColor(COLOR_TEXT);
svgGraphics2D.drawString(LABEL_TEXT, X_MARGIN, Y_OFFSET_TEXT);
// draw result background
svgGraphics2D.setColor(status.displayBackgroundColor());
svgGraphics2D.fillRoundRect(LABEL_WIDTH, 0, status.displayWidth(), CANVAS_HEIGHT, BACKGROUND_CORNER_ARC_DIAMETER, BACKGROUND_CORNER_ARC_DIAMETER);
svgGraphics2D.fillRect(LABEL_WIDTH, 0, BACKGROUND_CORNER_ARC_DIAMETER, CANVAS_HEIGHT);
// draw result text shadow
svgGraphics2D.setColor(COLOR_SHADOW);
svgGraphics2D.drawString(status.displayText(), LABEL_WIDTH + X_MARGIN, 15);
// draw result text
svgGraphics2D.setColor(COLOR_TEXT);
svgGraphics2D.drawString(status.displayText(), LABEL_WIDTH + X_MARGIN, 14);
return svgGraphics2D;
}
Examples of produced images (depending on parameters passed to the generateFor() method) can be seen on GitHub as well.
This code works fine, however currently the weight of a generated image is more or less 2KB, which is almost 3 times heavier than travis-ci badges that weight more or less 700 Bytes. Therefor I have the feeling that generated images could be simplified, sized down to ~1KB.
How can I achieve this using Apache Batik ? Should I use another library or use another approach ?
Thanks in advance for your insight and recommendations !
I tried generating your SVG using JFreeSVG 3.0, and with the GZIP option it creates files around 570 bytes. In plain text the SVG is around 1.7 kbytes.
Here is the test program I ran (based on your code, you'll also need your QualityGateStatus class to run this):
/*
* qualinsight-plugins-sonarqube-status
* Copyright (c) 2015, QualInsight
* http://www.qualinsight.com/
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation, either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, you can retrieve a copy
* from <http://www.gnu.org/licenses/>.
*/
import java.awt.Color;
import java.awt.Font;
import java.io.File;
import java.io.IOException;
import org.jfree.graphics2d.svg.SVGGraphics2D;
import org.jfree.graphics2d.svg.SVGUtils;
public final class SVGImageGenerator {
private static final int FONT_SIZE = 11;
private static final Font FONT_FAMILY = new Font("Verdana", Font.PLAIN, FONT_SIZE);
private static final int X_MARGIN = 4;
private static final int CANVAS_HEIGHT = 20;
private static final int LABEL_WIDTH = 46;
private static final String LABEL_TEXT = "quality";
private static final int BACKGROUND_CORNER_ARC_DIAMETER = 6;
private static final Color COLOR_BACKGROUND_LABEL = new Color(85, 85, 85, 255);
private static final Color COLOR_SHADOW = new Color(0, 0, 0, 85);
private static final Color COLOR_TEXT = new Color(255, 255, 255, 255);
private static final int Y_OFFSET_SHADOW = 14;
private static final int Y_OFFSET_TEXT = 14;
private static String generateFor(final QualityGateStatus status) {
// new SVG graphics
final SVGGraphics2D svgGraphics2D = new SVGGraphics2D(LABEL_WIDTH + status.displayWidth(), CANVAS_HEIGHT);
// set font
svgGraphics2D.setFont(FONT_FAMILY);
// draw Label background
svgGraphics2D.setColor(COLOR_BACKGROUND_LABEL);
svgGraphics2D.fillRoundRect(0, 0, LABEL_WIDTH, CANVAS_HEIGHT, BACKGROUND_CORNER_ARC_DIAMETER, BACKGROUND_CORNER_ARC_DIAMETER);
svgGraphics2D.fillRect(LABEL_WIDTH - BACKGROUND_CORNER_ARC_DIAMETER, 0, BACKGROUND_CORNER_ARC_DIAMETER, CANVAS_HEIGHT);
// draw Label text shadow
svgGraphics2D.setColor(COLOR_SHADOW);
svgGraphics2D.drawString(LABEL_TEXT, X_MARGIN, Y_OFFSET_SHADOW);
// draw Label text
svgGraphics2D.setColor(COLOR_TEXT);
svgGraphics2D.drawString(LABEL_TEXT, X_MARGIN, Y_OFFSET_TEXT);
// draw result background
svgGraphics2D.setColor(status.displayBackgroundColor());
svgGraphics2D.fillRoundRect(LABEL_WIDTH, 0, status.displayWidth(), CANVAS_HEIGHT, BACKGROUND_CORNER_ARC_DIAMETER, BACKGROUND_CORNER_ARC_DIAMETER);
svgGraphics2D.fillRect(LABEL_WIDTH, 0, BACKGROUND_CORNER_ARC_DIAMETER, CANVAS_HEIGHT);
// draw result text shadow
svgGraphics2D.setColor(COLOR_SHADOW);
svgGraphics2D.drawString(status.displayText(), LABEL_WIDTH + X_MARGIN, 15);
// draw result text
svgGraphics2D.setColor(COLOR_TEXT);
svgGraphics2D.drawString(status.displayText(), LABEL_WIDTH + X_MARGIN, 14);
return svgGraphics2D.getSVGElement();
}
public static void main(String[] args) {
try {
SVGUtils.writeToSVG(new File("error.svgz"), generateFor(QualityGateStatus.ERROR), true);
SVGUtils.writeToSVG(new File("none.svgz"), generateFor(QualityGateStatus.NONE), true);
SVGUtils.writeToSVG(new File("ok.svgz"), generateFor(QualityGateStatus.OK), true);
SVGUtils.writeToSVG(new File("server_error.svgz"), generateFor(QualityGateStatus.SERVER_ERROR), true);
SVGUtils.writeToSVG(new File("warn.svgz"), generateFor(QualityGateStatus.WARN), true);
} catch (IOException ex) {
ex.printStackTrace();
}
}
}

Scaling an image with LibGDX SpriteBatches

I have my image (for the sake of explaining, lets call it Image.png) and I'm trying to get it to scale to properly fit in my Bodies I have drawn. The bodies and everything work with the debug but I'm not a fan of it.. I'm using a SpriteBatch to draw the background image onto the screen(it would be nice to scale that too). How would I scaleImage.png to the same size/position as a Dynamic body that has been rendered?
EDIT:
While drawing the images, I cant get them to match up with the debug render Bodies..
Creating Body:
BodyDef bodydef2 = new BodyDef();
bodydef2.type = BodyType.DynamicBody;
bodydef2.position.set(camera.viewportWidth + 30.0f, (int)(Math.random()*camera.viewportHeight)%(LastPlatformY+5)+20);
//System.out.println(bodydef2.position.y + " " + LastPlatformY);
Body block = world.createBody(bodydef2);
PolygonShape Shape2 = new PolygonShape();
Shape2.setAsBox(750*WORLD_TO_BOX, 200*WORLD_TO_BOX);
FixtureDef fixtureDef2 = new FixtureDef();
fixtureDef2.shape = Shape2;
fixtureDef2.density = 1000.0f;
fixtureDef2.friction = 0.0f;
fixtureDef2.restitution = 0;
block.setLinearVelocity(new Vector2((float) (Platform_Velocity*-1), 0));
block.createFixture(fixtureDef2);
//Lock 'block' to X-Axis, Relative to floor.
PrismaticJointDef jointDef = new PrismaticJointDef();
jointDef.collideConnected = true;
jointDef.initialize(block, groundBody, block.getWorldCenter(), new Vector2(1, 0));
world.createJoint(jointDef);
Platforms.add(block);
Platforms_Created++;
LastPlatformY = (int)bodydef2.position.y;
Drawing Image:
sp.draw(platforms, (float)(Platforms.get(i).getPosition().x), (float)(Platforms.get(i).getPosition().y), 75,20);
EDIT #2:
turns out that if your camera is smaller than the size of your screen you have to do some compensation to account for that variation in positions.. Problem solved, thanks!
Just save the size of your body in two variables while creating your body and then call the appropriate draw method.
To get the position of your object call body.getPosition().
For example
Texture t = assetManager.get("your texture", Texture.class);
BodyDef bodyDef = new BodyDef();
body.type = BodyType.DynamicBody
float width = 64 * WORLD_TO_BOX;
float height = 64 * WORLD_TO_BOX;
Shape shape = new PolygonShape();
float[] points = new float[]{0,0,width,0,width,height,0, height};
shape.set(points);
FixtureDef def = new FixtureDef();
def.shape = shape;
...
body.createFixture(def);
shape.dispose();
And later when you want to draw
public void render(Spritebatch batch) {
batch.draw(t, body.getPosition().x * BOX_TO_WORLD, body.getPosition().y * BOX_TO_WORLD, width * BOX_TO_WORLD, height * BOX_TO_WORLD);
}

java print api - printing JComponent at 300dpi

please tell me if I am doing something wrong. I want to print barcodes onto labels, so I need high quality printout for these barcodes so I am pushing printer to print in 300dpi. What I've done:
made a big JFrame; width: 2490px, height: 3515px so it represents A4 paper in 1:1 measure (this is A4 paper resolution if print is to be 300dpi)
draw 40 barcode images onto contentPane of that JFrame
setup print attributes so it will print in 300dpi:
PrintRequestAttributeSet aset =
new HashPrintRequestAttributeSet();
PrinterResolution pr =
new PrinterResolution(300,300,PrinterResolution.DPI);
MediaPrintableArea mpa=new MediaPrintableArea(8,21,
210-16, 296-42, MediaPrintableArea.MM);
attribute set is filled with this data:
aset.add( mpa );
aset.add( pr );
aset.add( MediaSizeName.ISO_A4 );
aset.add( new Copies(1) );
aset.add(OrientationRequested.PORTRAIT );
aset.add(PrintQuality.HIGH);
aset.add( Fidelity.FIDELITY_TRUE );
printJob.setPrintable(this);
printJob.print(aset);
this class has print method:
public int print(Graphics g, PageFormat pageFormat, int pageIndex) {
if (pageIndex > 0) {
return(NO_SUCH_PAGE);
} else {
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pageFormat.getImageableX(),pageFormat.getImageableY());
disableDoubleBuffering(componentToBePrinted);
componentToBePrinted.paint(g2d);
enableDoubleBuffering(componentToBePrinted);
return(PAGE_EXISTS);
}
I need to have 40 barcodes on that A4 sheet, each in size 48.5mm x 25.4mm.
What is printed out on paper is 6 barcodes each doubled in size of 104mm x 46mm (that is in width almost half of page's width) which fulfilled whole paper.
Any idea, what can I do wrong?
Your resolution is probably being set to 72 dpi which has the effect of increasing the size of the image.

Categories