mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-14 18:03:44 +00:00
8251928: [macos] the printer DPI always be 72, cause some content lost when print out
Reviewed-by: psadhukhan, prr
This commit is contained in:
parent
e1c952608d
commit
76a1109d6f
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -32,6 +32,7 @@ import java.awt.GraphicsDevice;
|
||||
import java.awt.Rectangle;
|
||||
import java.awt.Transparency;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.ColorModel;
|
||||
import java.awt.image.VolatileImage;
|
||||
@ -45,10 +46,16 @@ public final class CPrinterGraphicsConfig extends GraphicsConfiguration {
|
||||
|
||||
private final GraphicsDevice device;
|
||||
private final PageFormat pf;
|
||||
private final AffineTransform deviceTransform;
|
||||
|
||||
public CPrinterGraphicsConfig(PageFormat pf) {
|
||||
this(pf, null);
|
||||
}
|
||||
|
||||
CPrinterGraphicsConfig(PageFormat pf, AffineTransform deviceTransform) {
|
||||
this.device = new CPrinterDevice(this);
|
||||
this.pf = pf;
|
||||
this.deviceTransform = deviceTransform;
|
||||
}
|
||||
|
||||
public PageFormat getPageFormat() {
|
||||
@ -178,7 +185,8 @@ public final class CPrinterGraphicsConfig extends GraphicsConfiguration {
|
||||
*/
|
||||
@Override
|
||||
public AffineTransform getDefaultTransform() {
|
||||
return new AffineTransform();
|
||||
return deviceTransform == null ?
|
||||
new AffineTransform() : new AffineTransform(deviceTransform);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,6 +232,10 @@ public final class CPrinterGraphicsConfig extends GraphicsConfiguration {
|
||||
*/
|
||||
@Override
|
||||
public Rectangle getBounds() {
|
||||
return new Rectangle(0, 0, (int)pf.getWidth(), (int)pf.getHeight());
|
||||
Point2D.Double pt = new Point2D.Double(pf.getWidth(), pf.getHeight());
|
||||
Point2D.Double transformedPt = new Point2D.Double();
|
||||
getDefaultTransform().transform(pt, transformedPt);
|
||||
return new Rectangle(0, 0,
|
||||
(int)transformedPt.getX(), (int)transformedPt.getY());
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,6 +35,7 @@ import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.SecondaryLoop;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.print.Pageable;
|
||||
@ -85,6 +86,9 @@ public final class CPrinterJob extends RasterPrinterJob {
|
||||
// future compatibility and the state keeping that it handles.
|
||||
|
||||
private static String sShouldNotReachHere = "Should not reach here.";
|
||||
private static final double USER_SPACE_DPI = 72.0;
|
||||
private static final int DEFAULT_DOC_DPI_X = 300;
|
||||
private static final int DEFAULT_DOC_DPI_Y = 300;
|
||||
|
||||
private volatile SecondaryLoop printingLoop;
|
||||
private AtomicReference<Throwable> printErrorRef = new AtomicReference<>();
|
||||
@ -110,6 +114,9 @@ public final class CPrinterJob extends RasterPrinterJob {
|
||||
private final Object fNSPrintInfoLock = new Object();
|
||||
private final Object disposerReferent = new Object();
|
||||
|
||||
private double hRes = DEFAULT_DOC_DPI_X;
|
||||
private double vRes = DEFAULT_DOC_DPI_Y;
|
||||
|
||||
static {
|
||||
// AWT has to be initialized for the native code to function correctly.
|
||||
Toolkit.getDefaultToolkit();
|
||||
@ -461,8 +468,7 @@ public final class CPrinterJob extends RasterPrinterJob {
|
||||
*/
|
||||
@Override
|
||||
protected double getXRes() {
|
||||
// NOTE: This is not used in the CPrinterJob code path.
|
||||
return 0;
|
||||
return hRes;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -471,8 +477,31 @@ public final class CPrinterJob extends RasterPrinterJob {
|
||||
*/
|
||||
@Override
|
||||
protected double getYRes() {
|
||||
// NOTE: This is not used in the CPrinterJob code path.
|
||||
return 0;
|
||||
return vRes;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setXYRes(double x, double y) {
|
||||
hRes = x;
|
||||
vRes = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resolution in dots per inch across the width
|
||||
* of the page. This method take into account the page orientation.
|
||||
*/
|
||||
private double getXRes(PageFormat pageFormat) {
|
||||
return pageFormat.getOrientation() == PageFormat.PORTRAIT ?
|
||||
getXRes() : getYRes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resolution in dots per inch across the height
|
||||
* of the page. This method take into account the page orientation.
|
||||
*/
|
||||
private double getYRes(PageFormat pageFormat) {
|
||||
return pageFormat.getOrientation() == PageFormat.PORTRAIT ?
|
||||
getYRes() : getXRes();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -817,7 +846,11 @@ public final class CPrinterJob extends RasterPrinterJob {
|
||||
// This is called from the native side.
|
||||
Runnable r = new Runnable() { public void run() {
|
||||
try {
|
||||
SurfaceData sd = CPrinterSurfaceData.createData(page, context); // Just stores page into an ivar
|
||||
AffineTransform deviceTransform = new AffineTransform(
|
||||
getXRes(page) / USER_SPACE_DPI, 0, 0,
|
||||
getYRes(page) / USER_SPACE_DPI, 0, 0);
|
||||
SurfaceData sd = CPrinterSurfaceData
|
||||
.createData(page, deviceTransform, context); // Just stores page into an ivar
|
||||
if (defaultFont == null) {
|
||||
defaultFont = new Font("Dialog", Font.PLAIN, 12);
|
||||
}
|
||||
@ -873,6 +906,9 @@ public final class CPrinterJob extends RasterPrinterJob {
|
||||
Rectangle2D pageFormatArea =
|
||||
getPageFormatArea(pageFormat);
|
||||
initPrinterGraphics(peekGraphics, pageFormatArea);
|
||||
double scaleX = getXRes(pageFormat) / USER_SPACE_DPI;
|
||||
double scaleY = getYRes(pageFormat) / USER_SPACE_DPI;
|
||||
peekGraphics.scale(scaleX, scaleY);
|
||||
|
||||
// Do the assignment here!
|
||||
ret[0] = pageFormat;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -26,6 +26,7 @@
|
||||
package sun.lwawt.macosx;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.*;
|
||||
import java.awt.print.PageFormat;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -40,8 +41,8 @@ public final class CPrinterSurfaceData extends OSXSurfaceData{
|
||||
// public static final SurfaceType IntArgbPQ = SurfaceType.IntArgb.deriveSubType(DESC_INT_ARGB_PQ);
|
||||
public static final SurfaceType IntRgbPQ = SurfaceType.IntRgb.deriveSubType(DESC_INT_RGB_PQ);
|
||||
|
||||
static SurfaceData createData(PageFormat pf, long context) {
|
||||
return new CPrinterSurfaceData(CPrinterGraphicsConfig.getConfig(pf), context);
|
||||
static SurfaceData createData(PageFormat pf, AffineTransform deviceTransform, long context) {
|
||||
return new CPrinterSurfaceData(new CPrinterGraphicsConfig(pf, deviceTransform), context);
|
||||
}
|
||||
|
||||
private CPrinterSurfaceData(GraphicsConfiguration gc, long context) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
@ -86,6 +86,8 @@ static jclass sjc_PAbortEx = NULL;
|
||||
GET_CPRINTERJOB_CLASS();
|
||||
DECLARE_METHOD(jm_printToPathGraphics, sjc_CPrinterJob, "printToPathGraphics",
|
||||
"(Lsun/print/PeekGraphics;Ljava/awt/print/PrinterJob;Ljava/awt/print/Printable;Ljava/awt/print/PageFormat;IJ)V");
|
||||
DECLARE_METHOD(jm_getXRes, sjc_CPrinterJob, "getXRes", "(Ljava/awt/print/PageFormat;)D");
|
||||
DECLARE_METHOD(jm_getYRes, sjc_CPrinterJob, "getYRes", "(Ljava/awt/print/PageFormat;)D");
|
||||
|
||||
// Create and draw into a new CPrinterGraphics with the current Context.
|
||||
assert(fCurPageFormat != NULL);
|
||||
@ -103,6 +105,21 @@ static jclass sjc_PAbortEx = NULL;
|
||||
|
||||
jlong context = ptr_to_jlong([printLoop context]);
|
||||
CGContextRef cgRef = (CGContextRef)[[printLoop context] graphicsPort];
|
||||
|
||||
// Scale from the java document DPI to the user space DPI
|
||||
jdouble hRes = (*env)->CallDoubleMethod(env, fPrinterJob, jm_getXRes, fCurPageFormat);
|
||||
CHECK_EXCEPTION();
|
||||
jdouble vRes = (*env)->CallDoubleMethod(env, fPrinterJob, jm_getYRes, fCurPageFormat);
|
||||
CHECK_EXCEPTION();
|
||||
if (hRes > 0 && vRes > 0) {
|
||||
double defaultDeviceDPI = 72;
|
||||
double scaleX = defaultDeviceDPI / hRes;
|
||||
double scaleY = defaultDeviceDPI / vRes;
|
||||
if (scaleX != 1 || scaleY != 1) {
|
||||
CGContextScaleCTM(cgRef, scaleX, scaleY);
|
||||
}
|
||||
}
|
||||
|
||||
CGContextSaveGState(cgRef); //04/28/2004: state needs to be saved here due to addition of lazy state management
|
||||
|
||||
(*env)->CallVoidMethod(env, fPrinterJob, jm_printToPathGraphics, fCurPeekGraphics, fPrinterJob,
|
||||
|
||||
300
test/jdk/javax/print/PrintablePrintDPI.java
Normal file
300
test/jdk/javax/print/PrintablePrintDPI.java
Normal file
@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2025, BELLSOFT. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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 General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import javax.print.PrintService;
|
||||
import javax.print.PrintServiceLookup;
|
||||
import javax.print.attribute.HashPrintRequestAttributeSet;
|
||||
import javax.print.attribute.PrintRequestAttributeSet;
|
||||
import javax.print.attribute.ResolutionSyntax;
|
||||
import javax.print.attribute.standard.OrientationRequested;
|
||||
import javax.print.attribute.standard.PrinterResolution;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JList;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.ListCellRenderer;
|
||||
import javax.swing.border.EmptyBorder;
|
||||
import java.awt.BasicStroke;
|
||||
import java.awt.Color;
|
||||
import java.awt.Component;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GridLayout;
|
||||
import java.awt.Window;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.geom.GeneralPath;
|
||||
import java.awt.print.PageFormat;
|
||||
import java.awt.print.Printable;
|
||||
import java.awt.print.PrinterException;
|
||||
import java.awt.print.PrinterJob;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8251928
|
||||
* @key printer
|
||||
* @summary Printable.print method should reflect printer's DPI
|
||||
* @library /java/awt/regtesthelpers
|
||||
* @requires os.family == "mac"
|
||||
* @build PassFailJFrame
|
||||
* @run main/manual PrintablePrintDPI
|
||||
*/
|
||||
|
||||
public class PrintablePrintDPI implements Printable {
|
||||
|
||||
private static final double PAPER_DPI = 72.0;
|
||||
private static final int DEFAULT_DOCUMENT_DPI = 300;
|
||||
private static final int UNITS = ResolutionSyntax.DPI;
|
||||
|
||||
private static final String INSTRUCTIONS = """
|
||||
This test checks document DPI.
|
||||
To be able to run this test it is required to have a
|
||||
printer configured in your user environment.
|
||||
Test's steps:
|
||||
- Choose a printer.
|
||||
- Choose a printer resolution.
|
||||
- Press 'Print' button.
|
||||
Visual inspection of the printed pages is needed.
|
||||
A passing test will print chosen DPI on the printed page,
|
||||
2 vertical and 2 horizontal lines.
|
||||
""";
|
||||
|
||||
private final PrintService printService;
|
||||
private final PrinterResolution printerResolution;
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
PrintService[] availablePrintServices = PrintServiceLookup.lookupPrintServices(null, null);
|
||||
if (availablePrintServices.length == 0) {
|
||||
System.out.println("Available print services not found");
|
||||
return;
|
||||
}
|
||||
PassFailJFrame.builder()
|
||||
.instructions(INSTRUCTIONS)
|
||||
.testTimeOut(300)
|
||||
.title("Document DPI test")
|
||||
.testUI(createTestWindow(availablePrintServices))
|
||||
.build()
|
||||
.awaitAndCheck();
|
||||
}
|
||||
|
||||
private static Window createTestWindow(final PrintService[] availablePrintServices) {
|
||||
final Window frame = new JFrame("Choose service to test");
|
||||
JPanel pnlMain = new JPanel();
|
||||
pnlMain.setBorder(new EmptyBorder(5, 5, 5, 5));
|
||||
pnlMain.setLayout(new GridLayout(3, 1, 5, 5));
|
||||
JLabel lblServices = new JLabel("Available services");
|
||||
JLabel lblResolutions = new JLabel("Available resolutions");
|
||||
JButton btnPrint = new JButton("Print");
|
||||
btnPrint.setEnabled(false);
|
||||
JComboBox<PrinterResolution> cbResolutions = new JComboBox<>();
|
||||
cbResolutions.setRenderer(new ListCellRenderer<PrinterResolution>() {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<? extends PrinterResolution> list,
|
||||
PrinterResolution value,
|
||||
int index, boolean isSelected, boolean cellHasFocus) {
|
||||
String str = value == null ? "" :
|
||||
String.format("%dx%d DPI",
|
||||
value.getCrossFeedResolution(UNITS), value.getFeedResolution(UNITS));
|
||||
return new JLabel(str);
|
||||
}
|
||||
});
|
||||
cbResolutions.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
btnPrint.setEnabled(cbResolutions.getSelectedItem() != null);
|
||||
}
|
||||
});
|
||||
|
||||
JComboBox<PrintService> cbServices = new JComboBox<>();
|
||||
cbServices.setRenderer(new ListCellRenderer<PrintService>() {
|
||||
@Override
|
||||
public Component getListCellRendererComponent(JList<? extends PrintService> list, PrintService value,
|
||||
int index, boolean isSelected, boolean cellHasFocus) {
|
||||
return new JLabel(value == null ? "" : value.getName());
|
||||
}
|
||||
});
|
||||
cbServices.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
PrintService ps = (PrintService) cbServices.getSelectedItem();
|
||||
cbResolutions.removeAllItems();
|
||||
btnPrint.setEnabled(ps != null);
|
||||
if (ps != null) {
|
||||
PrinterResolution[] supportedResolutions = (PrinterResolution[])ps
|
||||
.getSupportedAttributeValues(PrinterResolution.class, null, null);
|
||||
if (supportedResolutions == null || supportedResolutions.length == 0) {
|
||||
cbResolutions.addItem(new PrinterResolution(DEFAULT_DOCUMENT_DPI, DEFAULT_DOCUMENT_DPI, UNITS));
|
||||
} else {
|
||||
for (PrinterResolution pr : supportedResolutions) {
|
||||
cbResolutions.addItem(pr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
for (PrintService ps : availablePrintServices) {
|
||||
cbServices.addItem(ps);
|
||||
}
|
||||
lblServices.setLabelFor(cbServices);
|
||||
btnPrint.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
PrintService printService = (PrintService) cbServices.getSelectedItem();
|
||||
PrinterResolution resolution = (PrinterResolution) cbResolutions.getSelectedItem();
|
||||
if (printService != null && resolution != null) {
|
||||
cbServices.setEnabled(false);
|
||||
cbResolutions.setEnabled(false);
|
||||
btnPrint.setEnabled(false);
|
||||
frame.setVisible(false);
|
||||
new PrintablePrintDPI(printService, resolution).test();
|
||||
}
|
||||
}
|
||||
});
|
||||
pnlMain.add(lblServices);
|
||||
pnlMain.add(cbServices);
|
||||
pnlMain.add(lblResolutions);
|
||||
pnlMain.add(cbResolutions);
|
||||
pnlMain.add(btnPrint);
|
||||
frame.add(pnlMain);
|
||||
frame.pack();
|
||||
return frame;
|
||||
}
|
||||
|
||||
private PrintablePrintDPI(PrintService printService, PrinterResolution printerResolution) {
|
||||
this.printService = printService;
|
||||
this.printerResolution = printerResolution;
|
||||
}
|
||||
|
||||
private void test() {
|
||||
System.out.printf("Perform test using %s and %dx%d DPI\n",
|
||||
printService.getName(),
|
||||
printerResolution.getCrossFeedResolution(UNITS),
|
||||
printerResolution.getFeedResolution(UNITS));
|
||||
|
||||
PrinterJob job = PrinterJob.getPrinterJob();
|
||||
try {
|
||||
PrintRequestAttributeSet attributeSet = new HashPrintRequestAttributeSet();
|
||||
attributeSet.add(printerResolution);
|
||||
attributeSet.add(OrientationRequested.PORTRAIT);
|
||||
job.setPrintService(printService);
|
||||
job.setPrintable(this);
|
||||
job.print(attributeSet);
|
||||
} catch (PrinterException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
|
||||
if (pageIndex > 0) {
|
||||
return NO_SUCH_PAGE;
|
||||
}
|
||||
final int[] deviceRes = printerResolution.getResolution(ResolutionSyntax.DPI);
|
||||
|
||||
Graphics2D g2 = (Graphics2D)graphics;
|
||||
|
||||
double hRes = g2.getTransform().getScaleX() * PAPER_DPI;
|
||||
double vRes = g2.getTransform().getScaleY() * PAPER_DPI;
|
||||
|
||||
// Horizontal and vertical document resolution
|
||||
g2.drawLine((int)pageFormat.getImageableX() + 5, (int)pageFormat.getImageableY() + 5,
|
||||
(int)pageFormat.getImageableX() + 50, (int)pageFormat.getImageableY() + 5);
|
||||
g2.drawString(Integer.toString((int)hRes),
|
||||
(int)pageFormat.getImageableX() + 60,
|
||||
(int)pageFormat.getImageableY() + 5 + g2.getFontMetrics().getHeight() / 2);
|
||||
|
||||
g2.drawLine((int)pageFormat.getImageableX() + 5, (int)pageFormat.getImageableY() + 5,
|
||||
(int)pageFormat.getImageableX() + 5, (int)pageFormat.getImageableY() + 50);
|
||||
g2.drawString(Integer.toString((int)vRes),
|
||||
(int)pageFormat.getImageableX() + 5, (int)pageFormat.getImageableY() + 60);
|
||||
|
||||
String msg = String.format(
|
||||
"Expected DPI: %dx%d, actual: %dx%d.\n",
|
||||
deviceRes[0], deviceRes[1], (int)hRes, (int)vRes);
|
||||
System.out.println(msg);
|
||||
|
||||
int msgX = (int)pageFormat.getImageableX() +
|
||||
g2.getFontMetrics().stringWidth(Integer.toString((int)vRes)) + 20;
|
||||
int msgY = (int)pageFormat.getImageableY() +
|
||||
g2.getFontMetrics().getHeight() + 20;
|
||||
|
||||
g2.drawString(msg, msgX, msgY);
|
||||
msgY += 20;
|
||||
g2.drawString("ScaleX: " + g2.getTransform().getScaleX(), msgX, msgY);
|
||||
msgY += 20;
|
||||
g2.drawString("ScaleY: " + g2.getTransform().getScaleY(), msgX, msgY);
|
||||
|
||||
final float lineWidth = 0.2f;
|
||||
double pageWidth = pageFormat.getWidth();
|
||||
double xLeft = pageWidth / 10;
|
||||
double yBase = pageFormat.getHeight() / 2;
|
||||
double xBase = pageFormat.getWidth() / 2;
|
||||
double yTop = yBase + 40;
|
||||
double yBottom = pageFormat.getHeight() - pageFormat.getHeight() / 10;
|
||||
|
||||
g2.setStroke(new BasicStroke(lineWidth));
|
||||
|
||||
double xRight = pageWidth - xLeft;
|
||||
g2.drawLine((int) xLeft, (int) yBase + 80,
|
||||
(int) (xRight),(int) yBase + 80);
|
||||
g2.drawLine((int) xBase, (int) yTop,
|
||||
(int) (xBase),(int) yBottom);
|
||||
|
||||
GeneralPath line = new GeneralPath();
|
||||
double halfLineWidth = lineWidth / 2.0f;
|
||||
double yLine = yBase + 100;
|
||||
double xLine = xBase + 20;
|
||||
line.moveTo(xLeft, yLine);
|
||||
line.lineTo(xLeft, yLine - halfLineWidth);
|
||||
line.lineTo(xLine - halfLineWidth, yLine - halfLineWidth);
|
||||
line.lineTo(xLine - halfLineWidth, yTop);
|
||||
line.lineTo(xLine + halfLineWidth, yTop);
|
||||
line.lineTo(xLine + halfLineWidth, yLine - halfLineWidth);
|
||||
line.lineTo(xRight, yLine - halfLineWidth);
|
||||
line.lineTo(xRight, yLine + halfLineWidth);
|
||||
line.lineTo(xLine + halfLineWidth, yLine + halfLineWidth);
|
||||
line.lineTo(xLine + halfLineWidth, yBottom);
|
||||
line.lineTo(xLine - halfLineWidth, yBottom);
|
||||
line.lineTo(xLine - halfLineWidth, yLine + halfLineWidth);
|
||||
line.lineTo(xLeft, yLine + halfLineWidth );
|
||||
line.closePath();
|
||||
g2.clip(line);
|
||||
|
||||
g2.setColor(Color.RED);
|
||||
|
||||
line.reset();
|
||||
line.moveTo(xLeft, yLine);
|
||||
line.lineTo(xRight, yLine);
|
||||
g2.draw(line);
|
||||
|
||||
line.reset();
|
||||
line.moveTo(xBase + 20, yTop);
|
||||
line.lineTo(xBase + 20, yBottom);
|
||||
g2.draw(line);
|
||||
|
||||
return PAGE_EXISTS;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user