Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

8256264: Printed GlyphVector outline with low DPI has bad quality on Windows #1183

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -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;
@@ -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 {
@@ -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() {
@@ -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));
}

/**
@@ -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
@@ -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()));
}

/**
@@ -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
@@ -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