diff --git a/src/share/classes/javax/print/attribute/standard/PrinterStateReasons.java b/src/share/classes/javax/print/attribute/standard/PrinterStateReasons.java index 14225b90e46f6d1bb68ba379faf015dd2d4c1c60..2b0e8d2ab0c081aeed37d7b1c13967baaf88765b 100644 --- a/src/share/classes/javax/print/attribute/standard/PrinterStateReasons.java +++ b/src/share/classes/javax/print/attribute/standard/PrinterStateReasons.java @@ -65,7 +65,7 @@ import javax.print.attribute.PrintServiceAttribute; * PrinterStateReason PrinterStateReason} objects to an existing * PrinterStateReasons object and remove them again. However, like class * {@link java.util.HashMap java.util.HashMap}, class PrinterStateReasons is - * bot multiple thread safe. If a PrinterStateReasons object will be used by + * not multiple thread safe. If a PrinterStateReasons object will be used by * multiple threads, be sure to synchronize its operations (e.g., using a * synchronized map view obtained from class {@link java.util.Collections * java.util.Collections}). diff --git a/src/share/classes/sun/font/Font2D.java b/src/share/classes/sun/font/Font2D.java index c344ebb70076c004770ae78fe7c908f95aaaf423..3a930d6502e601d529e4d0e3a029019f6052530e 100644 --- a/src/share/classes/sun/font/Font2D.java +++ b/src/share/classes/sun/font/Font2D.java @@ -320,21 +320,6 @@ public abstract class Font2D { lastFontStrike = new SoftReference(strike); StrikeCache.refStrike(strike); return strike; - } else { - /* We have found a cleared reference that has not yet - * been removed by the disposer. - * If we make this reference unreachable by removing it - * from the map,or overwriting it with a new reference to - * a new strike, then it is possible it may never be - * enqueued for disposal. That is the implication of - * the docs for java.lang.ref. So on finding a cleared - * reference, we need to dispose the native resources, - * if they haven't already been freed. - * The reference object needs to have a reference to - * the disposer instance for this to occur. - */ - ((StrikeCache.DisposableStrike)strikeRef) - .getDisposer().dispose(); } } /* When we create a new FontStrike instance, we *must* diff --git a/src/share/classes/sun/font/FontDesignMetrics.java b/src/share/classes/sun/font/FontDesignMetrics.java index 929c0d21dd8d42b9d03ad4dde3fbadc73970d9fc..e81c397fdea60ea3a7809cba1c21d83ca6248d9d 100644 --- a/src/share/classes/sun/font/FontDesignMetrics.java +++ b/src/share/classes/sun/font/FontDesignMetrics.java @@ -171,7 +171,7 @@ public final class FontDesignMetrics extends FontMetrics { * out we can clear the keys from the table. */ private static class KeyReference extends SoftReference - implements DisposerRecord { + implements DisposerRecord, Disposer.PollDisposable { static ReferenceQueue queue = Disposer.getQueue(); diff --git a/src/share/classes/sun/font/FontStrikeDisposer.java b/src/share/classes/sun/font/FontStrikeDisposer.java index 7245cc3736f0ac0c5cef8b4b2808e2e3d5f80edf..3ee33eccea61cb6a0f5d1e8f6582814c2cf13a93 100644 --- a/src/share/classes/sun/font/FontStrikeDisposer.java +++ b/src/share/classes/sun/font/FontStrikeDisposer.java @@ -25,6 +25,7 @@ package sun.font; +import sun.java2d.Disposer; import sun.java2d.DisposerRecord; /* @@ -49,7 +50,8 @@ import sun.java2d.DisposerRecord; * entries would be removed much more promptly than we need. */ -class FontStrikeDisposer implements DisposerRecord { +class FontStrikeDisposer + implements DisposerRecord, Disposer.PollDisposable { Font2D font2D; FontStrikeDesc desc; diff --git a/src/share/classes/sun/font/StrikeCache.java b/src/share/classes/sun/font/StrikeCache.java index 945b01f867ec3d4fbb814b97a98f735500b38b24..9e5b02a865031a9d1606d80768f6ff0103a82d50 100644 --- a/src/share/classes/sun/font/StrikeCache.java +++ b/src/share/classes/sun/font/StrikeCache.java @@ -254,9 +254,20 @@ public final class StrikeCache { // because they may be accessed on that thread at the time of the // disposal (for example, when the accel. cache is invalidated) - // REMIND: this look a bit heavyweight, but should be ok - // because strike disposal is a relatively infrequent operation, - // more worrisome is the necessity of getting a GC here. + // Whilst this is a bit heavyweight, in most applications + // strike disposal is a relatively infrequent operation, so it + // doesn't matter. But in some tests that use vast numbers + // of strikes, the switching back and forth is measurable. + // So the "pollRemove" call is added to batch up the work. + // If we are polling we know we've already been called back + // and can directly dispose the record. + // Also worrisome is the necessity of getting a GC here. + + if (Disposer.pollingQueue) { + doDispose(disposer); + return; + } + RenderQueue rq = null; GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); @@ -277,6 +288,7 @@ public final class StrikeCache { rq.flushAndInvokeNow(new Runnable() { public void run() { doDispose(disposer); + Disposer.pollRemove(); } }); } finally { diff --git a/src/share/classes/sun/java2d/Disposer.java b/src/share/classes/sun/java2d/Disposer.java index bf9ea8ad71a7b7146dbf4bbe19520aa64cb81ce1..4433a278d5d12d4792d8b93357a2d72dad96c6fc 100644 --- a/src/share/classes/sun/java2d/Disposer.java +++ b/src/share/classes/sun/java2d/Disposer.java @@ -29,6 +29,7 @@ import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.PhantomReference; import java.lang.ref.WeakReference; +import java.util.ArrayList; import java.util.Hashtable; /** @@ -146,6 +147,7 @@ public class Disposer implements Runnable { rec.dispose(); obj = null; rec = null; + clearDeferredRecords(); } catch (Exception e) { System.out.println("Exception while removing reference: " + e); e.printStackTrace(); @@ -153,6 +155,85 @@ public class Disposer implements Runnable { } } + /* + * This is a marker interface that, if implemented, means it + * doesn't acquire any special locks, and is safe to + * be disposed in the poll loop on whatever thread + * which happens to be the Toolkit thread, is in use. + */ + public static interface PollDisposable { + }; + + private static ArrayList deferredRecords = null; + + private static void clearDeferredRecords() { + if (deferredRecords == null || deferredRecords.isEmpty()) { + return; + } + for (int i=0;i(5); + } + deferredRecords.add(rec); + } + } + } catch (Exception e) { + System.out.println("Exception while removing reference: " + e); + e.printStackTrace(); + } finally { + pollingQueue = false; + } + } + private static native void initIDs(); /* diff --git a/src/share/classes/sun/java2d/SunGraphics2D.java b/src/share/classes/sun/java2d/SunGraphics2D.java index c63db02e75673be2538d1401b8ec62295db0ad86..951876eb23753a1c55b90083d6178fc1e6e6ef96 100644 --- a/src/share/classes/sun/java2d/SunGraphics2D.java +++ b/src/share/classes/sun/java2d/SunGraphics2D.java @@ -257,7 +257,6 @@ public final class SunGraphics2D font = defaultFont; } - loops = sd.getRenderLoops(this); setDevClip(sd.getBounds()); invalidatePipe(); } @@ -367,6 +366,7 @@ public final class SunGraphics2D shapepipe = invalidpipe; textpipe = invalidpipe; imagepipe = invalidpipe; + loops = null; } public void validatePipe() { diff --git a/src/share/classes/sun/java2d/SurfaceData.java b/src/share/classes/sun/java2d/SurfaceData.java index 65a04c23220c726a9981d5d85d045cff35387a8d..95ef18c85f4231af965664dd5d7c1e19ee2c15fe 100644 --- a/src/share/classes/sun/java2d/SurfaceData.java +++ b/src/share/classes/sun/java2d/SurfaceData.java @@ -69,6 +69,7 @@ import sun.java2d.pipe.DrawImagePipe; import sun.java2d.pipe.DrawImage; import sun.awt.SunHints; import sun.awt.image.SurfaceManager; +import sun.java2d.pipe.LoopBasedPipe; /** * This class provides various pieces of information relevant to a @@ -506,7 +507,6 @@ public abstract class SurfaceData sg2d.textpipe = solidTextRenderer; } sg2d.shapepipe = colorPrimitives; - sg2d.loops = getRenderLoops(sg2d); // assert(sg2d.surfaceData == this); } } else if (sg2d.compositeState == sg2d.COMP_CUSTOM) { @@ -603,9 +603,18 @@ public abstract class SurfaceData sg2d.textpipe = getTextPipe(sg2d, false /* AA==OFF */); sg2d.shapepipe = colorPrimitives; - sg2d.loops = getRenderLoops(sg2d); // assert(sg2d.surfaceData == this); } + + // check for loops + if (sg2d.textpipe instanceof LoopBasedPipe || + sg2d.shapepipe instanceof LoopBasedPipe || + sg2d.fillpipe instanceof LoopBasedPipe || + sg2d.drawpipe instanceof LoopBasedPipe || + sg2d.imagepipe instanceof LoopBasedPipe) + { + sg2d.loops = getRenderLoops(sg2d); + } } /* Return the text pipe to be used based on the graphics AA hint setting, diff --git a/src/share/classes/sun/java2d/pipe/AATextRenderer.java b/src/share/classes/sun/java2d/pipe/AATextRenderer.java index 389db9cbefdfbe41d4ffc34a36b57eb905036d01..602e5be5ef80340a8823863b6948b9d094b60982 100644 --- a/src/share/classes/sun/java2d/pipe/AATextRenderer.java +++ b/src/share/classes/sun/java2d/pipe/AATextRenderer.java @@ -34,8 +34,9 @@ import sun.font.GlyphList; * a solid source colour to an opaque destination. */ -public class AATextRenderer extends GlyphListLoopPipe { - +public class AATextRenderer extends GlyphListLoopPipe + implements LoopBasedPipe +{ protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) { sg2d.loops.drawGlyphListAALoop.DrawGlyphListAA(sg2d, sg2d.surfaceData, gl); diff --git a/src/share/classes/sun/java2d/pipe/GlyphListLoopPipe.java b/src/share/classes/sun/java2d/pipe/GlyphListLoopPipe.java index cbe76016cf748c9670972911e9de2714a133a019..385a768cf9e9f4bb6ddbfc5e8d66143e1f2bbcd7 100644 --- a/src/share/classes/sun/java2d/pipe/GlyphListLoopPipe.java +++ b/src/share/classes/sun/java2d/pipe/GlyphListLoopPipe.java @@ -36,8 +36,9 @@ import sun.font.GlyphList; * the installed loop may not match the glyphvector. */ -public abstract class GlyphListLoopPipe extends GlyphListPipe { - +public abstract class GlyphListLoopPipe extends GlyphListPipe + implements LoopBasedPipe +{ protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl, int aaHint) { switch (aaHint) { diff --git a/src/share/classes/sun/java2d/pipe/LoopBasedPipe.java b/src/share/classes/sun/java2d/pipe/LoopBasedPipe.java new file mode 100644 index 0000000000000000000000000000000000000000..34b9067335c4564dd67bf1fc42f769edaada6dda --- /dev/null +++ b/src/share/classes/sun/java2d/pipe/LoopBasedPipe.java @@ -0,0 +1,37 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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. Sun designates this + * particular file as subject to the "Classpath" exception as provided + * by Sun in the LICENSE file that accompanied this code. + * + * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +package sun.java2d.pipe; + +/** + * This is a marker interface used by Pipes that need RenderLoops. + * RenderLoops are validated in SurfaceData when a pipe is recognised to + * implement this interface. + * + * @author Mario Torre + */ +public interface LoopBasedPipe { + +} diff --git a/src/share/classes/sun/java2d/pipe/LoopPipe.java b/src/share/classes/sun/java2d/pipe/LoopPipe.java index 93334e56fac5098859b7a66c92e00df46871edd9..a7d2c1dae23e26f7e7200225859ced9fbf305c9b 100644 --- a/src/share/classes/sun/java2d/pipe/LoopPipe.java +++ b/src/share/classes/sun/java2d/pipe/LoopPipe.java @@ -46,7 +46,8 @@ import sun.awt.SunHints; public class LoopPipe implements PixelDrawPipe, PixelFillPipe, - ShapeDrawPipe + ShapeDrawPipe, + LoopBasedPipe { final static RenderingEngine RenderEngine = RenderingEngine.getInstance(); diff --git a/src/share/classes/sun/java2d/pipe/SolidTextRenderer.java b/src/share/classes/sun/java2d/pipe/SolidTextRenderer.java index 52d1a709a531232f48ad3cb56ac0344190c9315c..bb8778aba93a9334f8218ff53a29f8d11f69029e 100644 --- a/src/share/classes/sun/java2d/pipe/SolidTextRenderer.java +++ b/src/share/classes/sun/java2d/pipe/SolidTextRenderer.java @@ -35,8 +35,9 @@ import sun.font.GlyphList; * a solid source colour to an opaque destination. */ -public class SolidTextRenderer extends GlyphListLoopPipe { - +public class SolidTextRenderer extends GlyphListLoopPipe + implements LoopBasedPipe +{ protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) { sg2d.loops.drawGlyphListLoop.DrawGlyphList(sg2d, sg2d.surfaceData, gl); } diff --git a/src/share/classes/sun/java2d/pipe/SpanShapeRenderer.java b/src/share/classes/sun/java2d/pipe/SpanShapeRenderer.java index 574ebed818842409068d5a2156c9db7fbd577578..a02b761c8dcf97f12215b58373ca47b84a1e35d3 100644 --- a/src/share/classes/sun/java2d/pipe/SpanShapeRenderer.java +++ b/src/share/classes/sun/java2d/pipe/SpanShapeRenderer.java @@ -65,7 +65,9 @@ public abstract class SpanShapeRenderer implements ShapeDrawPipe { } } - public static class Simple extends SpanShapeRenderer { + public static class Simple extends SpanShapeRenderer + implements LoopBasedPipe + { public Object startSequence(SunGraphics2D sg, Shape s, Rectangle devR, int[] bbox) { return sg; diff --git a/src/share/classes/sun/java2d/pisces/Renderer.java b/src/share/classes/sun/java2d/pisces/Renderer.java index 3ada6c73600118ebf22387cffda6a2333b381ca7..2aba41121611d35314763e1b0263063362ff7f19 100644 --- a/src/share/classes/sun/java2d/pisces/Renderer.java +++ b/src/share/classes/sun/java2d/pisces/Renderer.java @@ -775,10 +775,12 @@ public class Renderer extends LineSink { // Free sorting arrays if larger than maximum size private void crossingListFinished() { - if (crossings.length > DEFAULT_CROSSINGS_SIZE) { + if (crossings != null && crossings.length > DEFAULT_CROSSINGS_SIZE) { crossings = new int[DEFAULT_CROSSINGS_SIZE]; } - if (crossingIndices.length > DEFAULT_INDICES_SIZE) { + if (crossingIndices != null && + crossingIndices.length > DEFAULT_INDICES_SIZE) + { crossingIndices = new int[DEFAULT_INDICES_SIZE]; } } diff --git a/src/share/native/sun/awt/image/jpeg/imageioJPEG.c b/src/share/native/sun/awt/image/jpeg/imageioJPEG.c index 7d39c61e02f000ce741fa2aa00467e3b260c35f8..e25c07a6a0d5c4d984ce4be81dc3ad66adb59074 100644 --- a/src/share/native/sun/awt/image/jpeg/imageioJPEG.c +++ b/src/share/native/sun/awt/image/jpeg/imageioJPEG.c @@ -1437,6 +1437,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_initJPEGImageReader JNU_ThrowByName( env, "java/lang/OutOfMemoryError", "Initializing Reader"); + free(cinfo); return 0; } @@ -1473,6 +1474,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_initJPEGImageReader JNU_ThrowByName(env, "java/lang/OutOfMemoryError", "Initializing Reader"); + imageio_dispose((j_common_ptr)cinfo); return 0; } cinfo->src->bytes_in_buffer = 0; @@ -1489,6 +1491,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageReader_initJPEGImageReader JNU_ThrowByName( env, "java/lang/OutOfMemoryError", "Initializing Reader"); + imageio_dispose((j_common_ptr)cinfo); return 0; } return (jlong) ret; @@ -2420,8 +2423,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initJPEGImageWriter JNU_ThrowByName( env, "java/lang/OutOfMemoryError", "Initializing Writer"); - free(cinfo); - free(jerr); + imageio_dispose((j_common_ptr)cinfo); return 0; } @@ -2439,8 +2441,7 @@ Java_com_sun_imageio_plugins_jpeg_JPEGImageWriter_initJPEGImageWriter JNU_ThrowByName( env, "java/lang/OutOfMemoryError", "Initializing Writer"); - free(cinfo); - free(jerr); + imageio_dispose((j_common_ptr)cinfo); return 0; } return (jlong) ret; diff --git a/src/share/native/sun/awt/medialib/awt_ImagingLib.c b/src/share/native/sun/awt/medialib/awt_ImagingLib.c index 157827fef29b105239e913872854a3c7c98cc02e..07f9187ffc88120242e9841e7270355c5f059388 100644 --- a/src/share/native/sun/awt/medialib/awt_ImagingLib.c +++ b/src/share/native/sun/awt/medialib/awt_ImagingLib.c @@ -960,21 +960,15 @@ Java_sun_awt_image_ImagingLib_transformRaster(JNIEnv *env, jobject this, mlib_filter filter; unsigned int *dP; - if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) { - JNU_ThrowOutOfMemoryError(env, "Out of memory"); - return -1; - } - - if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) { - JNU_ThrowOutOfMemoryError(env, "Out of memory"); - free(srcRasterP); - return -1; - } - /* This function requires a lot of local refs ??? Is 64 enough ??? */ if ((*env)->EnsureLocalCapacity(env, 64) < 0) return 0; + if (s_nomlib) return 0; + if (s_timeIt) { + (*start_timer)(3600); + } + switch(interpType) { case java_awt_image_AffineTransformOp_TYPE_BILINEAR: filter = MLIB_BILINEAR; @@ -990,9 +984,15 @@ Java_sun_awt_image_ImagingLib_transformRaster(JNIEnv *env, jobject this, return -1; } - if (s_nomlib) return 0; - if (s_timeIt) { - (*start_timer)(3600); + if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) { + JNU_ThrowOutOfMemoryError(env, "Out of memory"); + return -1; + } + + if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) { + JNU_ThrowOutOfMemoryError(env, "Out of memory"); + free(srcRasterP); + return -1; } if ((*env)->GetArrayLength(env, jmatrix) < 6) { @@ -1215,6 +1215,9 @@ Java_sun_awt_image_ImagingLib_lookupByteBI(JNIEnv *env, jobject this, } if (tbl == NULL || table == NULL || jtable == NULL) { + if (tbl != NULL) free(tbl); + if (table != NULL) free(table); + if (jtable != NULL) free(jtable); awt_freeParsedImage(srcImageP, TRUE); awt_freeParsedImage(dstImageP, TRUE); JNU_ThrowNullPointerException(env, "NULL LUT"); @@ -1224,6 +1227,11 @@ Java_sun_awt_image_ImagingLib_lookupByteBI(JNIEnv *env, jobject this, for (i=0; i < jlen; i++) { jtable[i] = (*env)->GetObjectArrayElement(env, jtableArrays, i); if (jtable[i] == NULL) { + free(tbl); + free(table); + free(jtable); + awt_freeParsedImage(srcImageP, TRUE); + awt_freeParsedImage(dstImageP, TRUE); return 0; } } @@ -1232,6 +1240,9 @@ Java_sun_awt_image_ImagingLib_lookupByteBI(JNIEnv *env, jobject this, FALSE, &hint); if (nbands < 1) { /* Can't handle any custom images */ + free(tbl); + free(table); + free(jtable); awt_freeParsedImage(srcImageP, TRUE); awt_freeParsedImage(dstImageP, TRUE); return 0; @@ -1240,12 +1251,18 @@ Java_sun_awt_image_ImagingLib_lookupByteBI(JNIEnv *env, jobject this, /* Allocate the arrays */ if (allocateArray(env, srcImageP, &src, &sdata, TRUE, FALSE, FALSE) < 0) { /* Must be some problem */ + free(tbl); + free(table); + free(jtable); awt_freeParsedImage(srcImageP, TRUE); awt_freeParsedImage(dstImageP, TRUE); return 0; } if (allocateArray(env, dstImageP, &dst, &ddata, FALSE, FALSE, FALSE) < 0) { /* Must be some problem */ + free(tbl); + free(table); + free(jtable); freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL); awt_freeParsedImage(srcImageP, TRUE); awt_freeParsedImage(dstImageP, TRUE); @@ -1284,6 +1301,9 @@ Java_sun_awt_image_ImagingLib_lookupByteBI(JNIEnv *env, jobject this, (jbyte *) table[j], JNI_ABORT); } + free(tbl); + free(table); + free(jtable); freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL); awt_freeParsedImage(srcImageP, TRUE); awt_freeParsedImage(dstImageP, TRUE); @@ -1413,12 +1433,15 @@ Java_sun_awt_image_ImagingLib_lookupByteRaster(JNIEnv *env, /* Parse the source raster - reject custom images */ if ((status = awt_parseRaster(env, jsrc, srcRasterP)) <= 0) { + free(srcRasterP); + free(dstRasterP); return 0; } /* Parse the destination image - reject custom images */ if ((status = awt_parseRaster(env, jdst, dstRasterP)) <= 0) { awt_freeParsedRaster(srcRasterP, TRUE); + free(dstRasterP); return 0; } diff --git a/src/share/native/sun/font/freetypeScaler.c b/src/share/native/sun/font/freetypeScaler.c index 4028d4d97c4bb68abdd41452bfdd373c848235a0..93baaea47cd4e05d2ed0a4891d940d277e5ac6c9 100644 --- a/src/share/native/sun/font/freetypeScaler.c +++ b/src/share/native/sun/font/freetypeScaler.c @@ -102,9 +102,21 @@ Java_sun_font_FreetypeFontScaler_initIDs( } static void freeNativeResources(JNIEnv *env, FTScalerInfo* scalerInfo) { + void *stream; + if (scalerInfo == NULL) return; + //apparently Done_Face will only close the stream + // but will not relase the memory of stream structure. + // We need to free it explicitly to avoid leak. + //Direct access to the stream field might be not ideal solution as + // it is considred to be "private". + //Alternatively we could have stored pointer to the structure + // in the scalerInfo but this will increase size of the structure + // for no good reason + stream = scalerInfo->face->stream; + FT_Done_Face(scalerInfo->face); FT_Done_FreeType(scalerInfo->library); @@ -116,6 +128,10 @@ static void freeNativeResources(JNIEnv *env, FTScalerInfo* scalerInfo) { free(scalerInfo->fontData); } + if (stream != NULL) { + free(stream); + } + free(scalerInfo); } diff --git a/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java b/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java index f613c11883179c94d88455288abf65d623395775..943f6e73a063c3d67e79b3ab1a7584a5793a083c 100644 --- a/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java +++ b/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java @@ -388,7 +388,10 @@ public abstract class X11SurfaceData extends SurfaceData { // if a GlyphVector overrides the AA setting. // We use getRenderLoops() rather than setting solidloops // directly so that we get the appropriate loops in XOR mode. - sg2d.loops = getRenderLoops(sg2d); + if (sg2d.loops == null) { + // assert(some pipe will always be a LoopBasedPipe) + sg2d.loops = getRenderLoops(sg2d); + } } else { super.validatePipe(sg2d); } diff --git a/src/solaris/native/sun/awt/awt_GraphicsEnv.h b/src/solaris/native/sun/awt/awt_GraphicsEnv.h index 224c55404444c8faf80a8da30a4bd8cba5d80108..330b605143d1d557fb9061b9cefbaba9ce99d2a7 100644 --- a/src/solaris/native/sun/awt/awt_GraphicsEnv.h +++ b/src/solaris/native/sun/awt/awt_GraphicsEnv.h @@ -42,6 +42,10 @@ #include #include #include +#ifndef X_ShmAttach +#include +#include +#endif extern int XShmQueryExtension(); diff --git a/src/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java b/src/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java index e246a7fc63d13a1ee819bb97164b61c64d59e806..c55b54d9f6b1e0fb54783f8b21bfad31a4a42d97 100644 --- a/src/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java +++ b/src/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java @@ -210,7 +210,10 @@ public class GDIWindowSurfaceData extends SurfaceData { // if a GlyphVector overrides the AA setting. // We use getRenderLoops() rather than setting solidloops // directly so that we get the appropriate loops in XOR mode. - sg2d.loops = getRenderLoops(sg2d); + if (sg2d.loops == null) { + // assert(some pipe will always be a LoopBasedPipe) + sg2d.loops = getRenderLoops(sg2d); + } } else { super.validatePipe(sg2d); } diff --git a/src/windows/native/sun/windows/awt_PrintControl.cpp b/src/windows/native/sun/windows/awt_PrintControl.cpp index cc562ec0056999411a4b4837c0a09515251b653c..b68bb5f3bdd7328a7b27fff3eb04ef996e38de87 100644 --- a/src/windows/native/sun/windows/awt_PrintControl.cpp +++ b/src/windows/native/sun/windows/awt_PrintControl.cpp @@ -687,7 +687,7 @@ BOOL AwtPrintControl::InitPrintDialog(JNIEnv *env, // Now, set-up the struct for the real calls to ::PrintDlg and ::CreateDC pd.hwndOwner = hwndOwner; - pd.Flags = PD_ENABLEPRINTHOOK | PD_RETURNDC; + pd.Flags = PD_ENABLEPRINTHOOK | PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE; pd.lpfnPrintHook = (LPPRINTHOOKPROC)PrintDlgHook; if (env->CallBooleanMethod(printCtrl, AwtPrintControl::getCollateID)) { diff --git a/test/sun/java2d/pisces/Renderer/TestNPE.java b/test/sun/java2d/pisces/Renderer/TestNPE.java new file mode 100644 index 0000000000000000000000000000000000000000..440860c9272a52641cfb7c65024846596ad5a955 --- /dev/null +++ b/test/sun/java2d/pisces/Renderer/TestNPE.java @@ -0,0 +1,59 @@ +/* + * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, + * CA 95054 USA or visit www.sun.com if you need additional information or + * have any questions. + */ + +/** + * @test + * @bug 6887494 + * + * @summary Verifies that no NullPointerException is thrown in Pisces Renderer + * under certain circumstances. + * + * @run main TestNPE + */ + +import java.awt.*; +import java.awt.geom.*; +import java.awt.image.BufferedImage; + +public class TestNPE { + + private static void paint(Graphics g) { + Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setClip(0, 0, 0, 0); + g2d.setTransform( + new AffineTransform(4.0f, 0.0f, 0.0f, 4.0f, -1248.0f, -744.0f)); + g2d.draw(new Line2D.Float(131.21428571428572f, 33.0f, + 131.21428571428572f, 201.0f)); + } + + public static void main(String[] args) { + BufferedImage im = new BufferedImage(100, 100, + BufferedImage.TYPE_INT_ARGB); + + // Trigger exception in main thread. + Graphics g = im.getGraphics(); + paint(g); + } +}