提交 c0a10918 编写于 作者: L lana

Merge

......@@ -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}).
......
......@@ -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*
......
......@@ -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();
......
......@@ -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;
......
......@@ -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 {
......
......@@ -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<DisposerRecord> deferredRecords = null;
private static void clearDeferredRecords() {
if (deferredRecords == null || deferredRecords.isEmpty()) {
return;
}
for (int i=0;i<deferredRecords.size(); i++) {
try {
DisposerRecord rec = deferredRecords.get(i);
rec.dispose();
} catch (Exception e) {
System.out.println("Exception while disposing deferred rec.");
e.printStackTrace();
}
}
deferredRecords.clear();
}
/*
* Set to indicate the queue is presently being polled.
*/
public static volatile boolean pollingQueue = false;
/*
* The pollRemove() method is called back from a dispose method
* that is running on the toolkit thread and wants to
* dispose any pending refs that are safe to be disposed
* on that thread.
*/
public static void pollRemove() {
/* This should never be called recursively, so this check
* is just a safeguard against the unexpected.
*/
if (pollingQueue) {
return;
}
Object obj;
pollingQueue = true;
int freed = 0;
int deferred = 0;
try {
while ((obj = queue.poll()) != null
&& freed < 10000 && deferred < 100) {
freed++;
((Reference)obj).clear();
DisposerRecord rec = (DisposerRecord)records.remove(obj);
if (rec instanceof PollDisposable) {
rec.dispose();
obj = null;
rec = null;
} else {
if (rec == null) { // shouldn't happen, but just in case.
continue;
}
deferred++;
if (deferredRecords == null) {
deferredRecords = new ArrayList<DisposerRecord>(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();
/*
......
......@@ -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() {
......
......@@ -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,
......
......@@ -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);
......
......@@ -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) {
......
/*
* 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 <neugens@aicas.com>
*/
public interface LoopBasedPipe {
}
......@@ -46,7 +46,8 @@ import sun.awt.SunHints;
public class LoopPipe
implements PixelDrawPipe,
PixelFillPipe,
ShapeDrawPipe
ShapeDrawPipe,
LoopBasedPipe
{
final static RenderingEngine RenderEngine = RenderingEngine.getInstance();
......
......@@ -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);
}
......
......@@ -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;
......
......@@ -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];
}
}
......
......@@ -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;
......
......@@ -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;
}
......
......@@ -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);
}
......
......@@ -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);
}
......
......@@ -42,6 +42,10 @@
#include <sys/ipc.h>
#include <sys/shm.h>
#include <X11/extensions/XShm.h>
#ifndef X_ShmAttach
#include <X11/Xmd.h>
#include <X11/extensions/shmproto.h>
#endif
extern int XShmQueryExtension();
......
......@@ -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);
}
......
......@@ -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)) {
......
/*
* 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);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册