Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
8256264: Printed GlyphVector outline with low DPI has bad quality on …
…Windows

Reviewed-by: serb
  • Loading branch information
Alexander Scherbatiy committed Dec 4, 2020
1 parent 2b4a423 commit d6dd440
Show file tree
Hide file tree
Showing 4 changed files with 470 additions and 11 deletions.
Expand Up @@ -1760,8 +1760,8 @@ private void convertToWPath(PathIterator pathIter) {
/* Convert the quad path to a bezier.
*/
case PathIterator.SEG_QUADTO:
int lastX = wPrinterJob.getPenX();
int lastY = wPrinterJob.getPenY();
float lastX = wPrinterJob.getPenX();
float lastY = wPrinterJob.getPenY();
float c1x = lastX + (segment[0] - lastX) * 2 / 3;
float c1y = lastY + (segment[1] - lastY) * 2 / 3;
float c2x = segment[2] - (segment[2] - segment[0]) * 2/ 3;
Expand Down
118 changes: 109 additions & 9 deletions src/java.desktop/windows/classes/sun/awt/windows/WPrinterJob.java
Expand Up @@ -362,6 +362,10 @@ public void dispose() {

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

private static final float precisionScale = 1000.0f;
private int graphicsMode;
private double[] worldTransform = new double[6];

/* Static Initializations */

static {
Expand Down Expand Up @@ -953,11 +957,33 @@ private void setDevNames(long mPrintHDevNames) {
}

protected void beginPath() {
precisionScaleBegin();
beginPath(getPrintDC());
}

protected void endPath() {
endPath(getPrintDC());
precisionScaleEnd();
}

protected float precisionScaleUp(float value) {
return value * precisionScale;
}

protected float precisionScaleDown(float value) {
return value / precisionScale;
}

protected void precisionScaleBegin() {
graphicsMode = setAdvancedGraphicsMode();
getWorldTransform(worldTransform);
float invPrecisionScale = 1.0f / precisionScale;
scale(invPrecisionScale, invPrecisionScale);
}

protected void precisionScaleEnd() {
setWorldTransform(worldTransform);
setGraphicsMode(graphicsMode);
}

protected void closeFigure() {
Expand All @@ -969,20 +995,23 @@ protected void fillPath() {
}

protected void moveTo(float x, float y) {
moveTo(getPrintDC(), x, y);
moveTo(getPrintDC(),
precisionScaleUp(x), precisionScaleUp(y));
}

protected void lineTo(float x, float y) {
lineTo(getPrintDC(), x, y);
lineTo(getPrintDC(),
precisionScaleUp(x), precisionScaleUp(y));
}

protected void polyBezierTo(float control1x, float control1y,
float control2x, float control2y,
float endX, float endY) {

polyBezierTo(getPrintDC(), control1x, control1y,
control2x, control2y,
endX, endY);
polyBezierTo(getPrintDC(),
precisionScaleUp(control1x), precisionScaleUp(control1y),
precisionScaleUp(control2x), precisionScaleUp(control2y),
precisionScaleUp(endX), precisionScaleUp(endY));
}

/**
Expand All @@ -995,6 +1024,44 @@ protected void setPolyFillMode(int fillRule) {
setPolyFillMode(getPrintDC(), fillRule);
}

/**
* Set the GDI graphics mode to {@code GM_ADVANCED}.
*/
private int setAdvancedGraphicsMode() {
return setAdvancedGraphicsMode(getPrintDC());
}

/**
* Set the GDI graphics mode.
* The {@code mode} should
* be one of the following Windows constants:
* {@code GM_COMPATIBLE} or {@code GM_ADVANCED}.
*/
private int setGraphicsMode(int mode) {
return setGraphicsMode(getPrintDC(), mode);
}

/**
* Scale the GDI World Transform.
*/
private void scale(double scaleX, double scaleY) {
scale(getPrintDC(), scaleX, scaleY);
}

/**
* Get the GDI World Transform.
*/
private void getWorldTransform(double[] transform) {
getWorldTransform(getPrintDC(), transform);
}

/**
* Set the GDI World Transform.
*/
private void setWorldTransform(double[] transform) {
setWorldTransform(getPrintDC(), transform);
}

/*
* Create a Window's solid brush for the color specified
* by {@code (red, green, blue)}. Once the brush
Expand All @@ -1020,19 +1087,19 @@ protected void selectSolidBrush(Color color) {
* Return the x coordinate of the current pen
* position in the print device context.
*/
protected int getPenX() {
protected float getPenX() {

return getPenX(getPrintDC());
return precisionScaleDown(getPenX(getPrintDC()));
}


/**
* Return the y coordinate of the current pen
* position in the print device context.
*/
protected int getPenY() {
protected float getPenY() {

return getPenY(getPrintDC());
return precisionScaleDown(getPenY(getPrintDC()));
}

/**
Expand Down Expand Up @@ -1470,6 +1537,39 @@ protected native void polyBezierTo(long printDC,
*/
protected native void setPolyFillMode(long printDC, int fillRule);

/**
* Set the GDI graphics mode to {@code GM_ADVANCED}
* into the device context {@code printDC}.
*/
protected native int setAdvancedGraphicsMode(long printDC);

/**
* Set the GDI graphics mode to {@code GM_ADVANCED}
* into the device context {@code printDC}.
* The {@code mode} should
* be one of the following Windows constants:
* {@code GM_COMPATIBLE} or {@code GM_ADVANCED}.
*/
protected native int setGraphicsMode(long printDC, int mode);

/**
* Scale the GDI World Transform
* of the device context {@code printDC}.
*/
protected native void scale(long printDC, double scaleX, double scaleY);

/**
* Get the GDI World Transform
* from the device context {@code printDC}.
*/
protected native void getWorldTransform(long printDC, double[] transform);

/**
* Set the GDI World Transform
* into the device context {@code printDC}.
*/
protected native void setWorldTransform(long printDC, double[] transform);

/**
* Create a Window's solid brush for the color specified
* by {@code (red, green, blue)}. Once the brush
Expand Down
105 changes: 105 additions & 0 deletions src/java.desktop/windows/native/libawt/windows/awt_PrintJob.cpp
Expand Up @@ -1932,6 +1932,111 @@ JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_setPolyFillMode
CATCH_BAD_ALLOC;
}

/*
* Class: sun_awt_windows_WPrinterJob
* Method: setAdvancedGraphicsMode
* Signature: (J)I
*/
JNIEXPORT jint JNICALL Java_sun_awt_windows_WPrinterJob_setAdvancedGraphicsMode
(JNIEnv *env, jobject self, jlong printDC) {
TRY;

return (jint) ::SetGraphicsMode((HDC)printDC, GM_ADVANCED);

CATCH_BAD_ALLOC_RET(0);
}

/*
* Class: sun_awt_windows_WPrinterJob
* Method: setGraphicsMode
* Signature: (JI)I
*/
JNIEXPORT jint JNICALL Java_sun_awt_windows_WPrinterJob_setGraphicsMode
(JNIEnv *env, jobject self, jlong printDC, jint mode) {
TRY;

return (jint) ::SetGraphicsMode((HDC)printDC, mode);

CATCH_BAD_ALLOC_RET(0);
}

/*
* Class: sun_awt_windows_WPrinterJob
* Method: scale
* Signature: (JDD)V
*/
JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_scale
(JNIEnv *env, jobject self, jlong printDC, jdouble scaleX, jdouble scaleY) {
TRY;

XFORM xForm;

xForm.eM11 = (FLOAT) scaleX;
xForm.eM12 = (FLOAT) 0;
xForm.eM21 = (FLOAT) 0;
xForm.eM22 = (FLOAT) scaleY;
xForm.eDx = (FLOAT) 0;
xForm.eDy = (FLOAT) 0;

::ModifyWorldTransform((HDC)printDC, &xForm, MWT_RIGHTMULTIPLY);

CATCH_BAD_ALLOC;
}

/*
* Class: sun_awt_windows_WPrinterJob
* Method: getWorldTransform
* Signature: (J[D)V
*/
JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_getWorldTransform
(JNIEnv* env, jobject self, jlong printDC, jdoubleArray transform) {
TRY;

double elems[6];
XFORM xForm;

::GetWorldTransform((HDC)printDC, &xForm);

elems[0] = (double) xForm.eM11;
elems[1] = (double) xForm.eM12;
elems[2] = (double) xForm.eM21;
elems[3] = (double) xForm.eM22;
elems[4] = (double) xForm.eDx;
elems[5] = (double) xForm.eDy;

env->SetDoubleArrayRegion(transform, 0, 6, elems);

CATCH_BAD_ALLOC;
}

/*
* Class: sun_awt_windows_WPrinterJob
* Method: setWorldTransform
* Signature: (J[D)V
*/
JNIEXPORT void JNICALL Java_sun_awt_windows_WPrinterJob_setWorldTransform
(JNIEnv* env, jobject self, jlong printDC, jdoubleArray transform) {
TRY;

double *elems;
XFORM xForm;

elems = env->GetDoubleArrayElements(transform, 0);

xForm.eM11 = (FLOAT) elems[0];
xForm.eM12 = (FLOAT) elems[1];
xForm.eM21 = (FLOAT) elems[2];
xForm.eM22 = (FLOAT) elems[3];
xForm.eDx = (FLOAT) elems[4];
xForm.eDy = (FLOAT) elems[5];

::SetWorldTransform((HDC)printDC, &xForm);

env->ReleaseDoubleArrayElements(transform, elems, 0);

CATCH_BAD_ALLOC;
}

/*
* Class: sun_awt_windows_WPrinterJob
* Method: selectSolidBrush
Expand Down

1 comment on commit d6dd440

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.