Skip to content

Commit d6dd440

Browse files
author
Alexander Scherbatiy
committed
8256264: Printed GlyphVector outline with low DPI has bad quality on Windows
Reviewed-by: serb
1 parent 2b4a423 commit d6dd440

File tree

4 files changed

+470
-11
lines changed

4 files changed

+470
-11
lines changed

src/java.desktop/windows/classes/sun/awt/windows/WPathGraphics.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,8 +1760,8 @@ private void convertToWPath(PathIterator pathIter) {
17601760
/* Convert the quad path to a bezier.
17611761
*/
17621762
case PathIterator.SEG_QUADTO:
1763-
int lastX = wPrinterJob.getPenX();
1764-
int lastY = wPrinterJob.getPenY();
1763+
float lastX = wPrinterJob.getPenX();
1764+
float lastY = wPrinterJob.getPenY();
17651765
float c1x = lastX + (segment[0] - lastX) * 2 / 3;
17661766
float c1y = lastY + (segment[1] - lastY) * 2 / 3;
17671767
float c2x = segment[2] - (segment[2] - segment[0]) * 2/ 3;

src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java

Lines changed: 109 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,10 @@ public void dispose() {
362362

363363
private java.awt.peer.ComponentPeer dialogOwnerPeer = null;
364364

365+
private static final float precisionScale = 1000.0f;
366+
private int graphicsMode;
367+
private double[] worldTransform = new double[6];
368+
365369
/* Static Initializations */
366370

367371
static {
@@ -953,11 +957,33 @@ private void setDevNames(long mPrintHDevNames) {
953957
}
954958

955959
protected void beginPath() {
960+
precisionScaleBegin();
956961
beginPath(getPrintDC());
957962
}
958963

959964
protected void endPath() {
960965
endPath(getPrintDC());
966+
precisionScaleEnd();
967+
}
968+
969+
protected float precisionScaleUp(float value) {
970+
return value * precisionScale;
971+
}
972+
973+
protected float precisionScaleDown(float value) {
974+
return value / precisionScale;
975+
}
976+
977+
protected void precisionScaleBegin() {
978+
graphicsMode = setAdvancedGraphicsMode();
979+
getWorldTransform(worldTransform);
980+
float invPrecisionScale = 1.0f / precisionScale;
981+
scale(invPrecisionScale, invPrecisionScale);
982+
}
983+
984+
protected void precisionScaleEnd() {
985+
setWorldTransform(worldTransform);
986+
setGraphicsMode(graphicsMode);
961987
}
962988

963989
protected void closeFigure() {
@@ -969,20 +995,23 @@ protected void fillPath() {
969995
}
970996

971997
protected void moveTo(float x, float y) {
972-
moveTo(getPrintDC(), x, y);
998+
moveTo(getPrintDC(),
999+
precisionScaleUp(x), precisionScaleUp(y));
9731000
}
9741001

9751002
protected void lineTo(float x, float y) {
976-
lineTo(getPrintDC(), x, y);
1003+
lineTo(getPrintDC(),
1004+
precisionScaleUp(x), precisionScaleUp(y));
9771005
}
9781006

9791007
protected void polyBezierTo(float control1x, float control1y,
9801008
float control2x, float control2y,
9811009
float endX, float endY) {
9821010

983-
polyBezierTo(getPrintDC(), control1x, control1y,
984-
control2x, control2y,
985-
endX, endY);
1011+
polyBezierTo(getPrintDC(),
1012+
precisionScaleUp(control1x), precisionScaleUp(control1y),
1013+
precisionScaleUp(control2x), precisionScaleUp(control2y),
1014+
precisionScaleUp(endX), precisionScaleUp(endY));
9861015
}
9871016

9881017
/**
@@ -995,6 +1024,44 @@ protected void setPolyFillMode(int fillRule) {
9951024
setPolyFillMode(getPrintDC(), fillRule);
9961025
}
9971026

1027+
/**
1028+
* Set the GDI graphics mode to {@code GM_ADVANCED}.
1029+
*/
1030+
private int setAdvancedGraphicsMode() {
1031+
return setAdvancedGraphicsMode(getPrintDC());
1032+
}
1033+
1034+
/**
1035+
* Set the GDI graphics mode.
1036+
* The {@code mode} should
1037+
* be one of the following Windows constants:
1038+
* {@code GM_COMPATIBLE} or {@code GM_ADVANCED}.
1039+
*/
1040+
private int setGraphicsMode(int mode) {
1041+
return setGraphicsMode(getPrintDC(), mode);
1042+
}
1043+
1044+
/**
1045+
* Scale the GDI World Transform.
1046+
*/
1047+
private void scale(double scaleX, double scaleY) {
1048+
scale(getPrintDC(), scaleX, scaleY);
1049+
}
1050+
1051+
/**
1052+
* Get the GDI World Transform.
1053+
*/
1054+
private void getWorldTransform(double[] transform) {
1055+
getWorldTransform(getPrintDC(), transform);
1056+
}
1057+
1058+
/**
1059+
* Set the GDI World Transform.
1060+
*/
1061+
private void setWorldTransform(double[] transform) {
1062+
setWorldTransform(getPrintDC(), transform);
1063+
}
1064+
9981065
/*
9991066
* Create a Window's solid brush for the color specified
10001067
* by {@code (red, green, blue)}. Once the brush
@@ -1020,19 +1087,19 @@ protected void selectSolidBrush(Color color) {
10201087
* Return the x coordinate of the current pen
10211088
* position in the print device context.
10221089
*/
1023-
protected int getPenX() {
1090+
protected float getPenX() {
10241091

1025-
return getPenX(getPrintDC());
1092+
return precisionScaleDown(getPenX(getPrintDC()));
10261093
}
10271094

10281095

10291096
/**
10301097
* Return the y coordinate of the current pen
10311098
* position in the print device context.
10321099
*/
1033-
protected int getPenY() {
1100+
protected float getPenY() {
10341101

1035-
return getPenY(getPrintDC());
1102+
return precisionScaleDown(getPenY(getPrintDC()));
10361103
}
10371104

10381105
/**
@@ -1470,6 +1537,39 @@ protected native void polyBezierTo(long printDC,
14701537
*/
14711538
protected native void setPolyFillMode(long printDC, int fillRule);
14721539

1540+
/**
1541+
* Set the GDI graphics mode to {@code GM_ADVANCED}
1542+
* into the device context {@code printDC}.
1543+
*/
1544+
protected native int setAdvancedGraphicsMode(long printDC);
1545+
1546+
/**
1547+
* Set the GDI graphics mode to {@code GM_ADVANCED}
1548+
* into the device context {@code printDC}.
1549+
* The {@code mode} should
1550+
* be one of the following Windows constants:
1551+
* {@code GM_COMPATIBLE} or {@code GM_ADVANCED}.
1552+
*/
1553+
protected native int setGraphicsMode(long printDC, int mode);
1554+
1555+
/**
1556+
* Scale the GDI World Transform
1557+
* of the device context {@code printDC}.
1558+
*/
1559+
protected native void scale(long printDC, double scaleX, double scaleY);
1560+
1561+
/**
1562+
* Get the GDI World Transform
1563+
* from the device context {@code printDC}.
1564+
*/
1565+
protected native void getWorldTransform(long printDC, double[] transform);
1566+
1567+
/**
1568+
* Set the GDI World Transform
1569+
* into the device context {@code printDC}.
1570+
*/
1571+
protected native void setWorldTransform(long printDC, double[] transform);
1572+
14731573
/**
14741574
* Create a Window's solid brush for the color specified
14751575
* by {@code (red, green, blue)}. Once the brush

src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1932,6 +1932,111 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_setPolyFillMode
19321932
CATCH_BAD_ALLOC;
19331933
}
19341934

1935+
/*
1936+
* Class: sun_awt_windows_WPrinterJob
1937+
* Method: setAdvancedGraphicsMode
1938+
* Signature: (J)I
1939+
*/
1940+
JNIEXPORT jint JNICALL Java_sun_awt_windows_WPrinterJob_setAdvancedGraphicsMode
1941+
(JNIEnv *env, jobject self, jlong printDC) {
1942+
TRY;
1943+
1944+
return (jint) ::SetGraphicsMode((HDC)printDC, GM_ADVANCED);
1945+
1946+
CATCH_BAD_ALLOC_RET(0);
1947+
}
1948+
1949+
/*
1950+
* Class: sun_awt_windows_WPrinterJob
1951+
* Method: setGraphicsMode
1952+
* Signature: (JI)I
1953+
*/
1954+
JNIEXPORT jint JNICALL Java_sun_awt_windows_WPrinterJob_setGraphicsMode
1955+
(JNIEnv *env, jobject self, jlong printDC, jint mode) {
1956+
TRY;
1957+
1958+
return (jint) ::SetGraphicsMode((HDC)printDC, mode);
1959+
1960+
CATCH_BAD_ALLOC_RET(0);
1961+
}
1962+
1963+
/*
1964+
* Class: sun_awt_windows_WPrinterJob
1965+
* Method: scale
1966+
* Signature: (JDD)V
1967+
*/
1968+
JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_scale
1969+
(JNIEnv *env, jobject self, jlong printDC, jdouble scaleX, jdouble scaleY) {
1970+
TRY;
1971+
1972+
XFORM xForm;
1973+
1974+
xForm.eM11 = (FLOAT) scaleX;
1975+
xForm.eM12 = (FLOAT) 0;
1976+
xForm.eM21 = (FLOAT) 0;
1977+
xForm.eM22 = (FLOAT) scaleY;
1978+
xForm.eDx = (FLOAT) 0;
1979+
xForm.eDy = (FLOAT) 0;
1980+
1981+
::ModifyWorldTransform((HDC)printDC, &xForm, MWT_RIGHTMULTIPLY);
1982+
1983+
CATCH_BAD_ALLOC;
1984+
}
1985+
1986+
/*
1987+
* Class: sun_awt_windows_WPrinterJob
1988+
* Method: getWorldTransform
1989+
* Signature: (J[D)V
1990+
*/
1991+
JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_getWorldTransform
1992+
(JNIEnv* env, jobject self, jlong printDC, jdoubleArray transform) {
1993+
TRY;
1994+
1995+
double elems[6];
1996+
XFORM xForm;
1997+
1998+
::GetWorldTransform((HDC)printDC, &xForm);
1999+
2000+
elems[0] = (double) xForm.eM11;
2001+
elems[1] = (double) xForm.eM12;
2002+
elems[2] = (double) xForm.eM21;
2003+
elems[3] = (double) xForm.eM22;
2004+
elems[4] = (double) xForm.eDx;
2005+
elems[5] = (double) xForm.eDy;
2006+
2007+
env->SetDoubleArrayRegion(transform, 0, 6, elems);
2008+
2009+
CATCH_BAD_ALLOC;
2010+
}
2011+
2012+
/*
2013+
* Class: sun_awt_windows_WPrinterJob
2014+
* Method: setWorldTransform
2015+
* Signature: (J[D)V
2016+
*/
2017+
JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_setWorldTransform
2018+
(JNIEnv* env, jobject self, jlong printDC, jdoubleArray transform) {
2019+
TRY;
2020+
2021+
double *elems;
2022+
XFORM xForm;
2023+
2024+
elems = env->GetDoubleArrayElements(transform, 0);
2025+
2026+
xForm.eM11 = (FLOAT) elems[0];
2027+
xForm.eM12 = (FLOAT) elems[1];
2028+
xForm.eM21 = (FLOAT) elems[2];
2029+
xForm.eM22 = (FLOAT) elems[3];
2030+
xForm.eDx = (FLOAT) elems[4];
2031+
xForm.eDy = (FLOAT) elems[5];
2032+
2033+
::SetWorldTransform((HDC)printDC, &xForm);
2034+
2035+
env->ReleaseDoubleArrayElements(transform, elems, 0);
2036+
2037+
CATCH_BAD_ALLOC;
2038+
}
2039+
19352040
/*
19362041
* Class: sun_awt_windows_WPrinterJob
19372042
* Method: selectSolidBrush

0 commit comments

Comments
 (0)