📄 j3dgraphics2dimpl.java
字号:
/* * $RCSfile: J3DGraphics2DImpl.java,v $ * * Copyright (c) 2007 Sun Microsystems, Inc. All rights reserved. * * Use is subject to license terms. * * $Revision: 1.6 $ * $Date: 2007/02/09 17:18:06 $ * $State: Exp $ */package javax.media.j3d;import java.io.*;import java.util.*;import java.awt.*;import java.awt.event.*;import java.text.AttributedCharacterIterator;import java.awt.RenderingHints.Key;import java.awt.geom.*;import java.awt.image.*;import java.awt.image.renderable.RenderableImage;import java.awt.font.*;/** * Implementation class for J3DGraphics2D */final class J3DGraphics2DImpl extends J3DGraphics2D { private boolean hasBeenDisposed = false; private Graphics2D offScreenGraphics2D; private BufferedImage g3dImage = null; private byte[] data = null; private boolean isFlushed = true; private Canvas3D canvas3d; private int width, height; private int texWidth, texHeight; private int xmin, ymin, xmax, ymax; private Object extentLock = new Object(); private boolean abgr; private boolean initTexMap = false; private boolean strokeSet=false; private Point2D.Float ptSrc = new Point2D.Float(); private Point2D.Float ptDst1 = new Point2D.Float(); private Point2D.Float ptDst2 = new Point2D.Float(); private Color xOrModeColor = null; private volatile boolean initCtx = false; private volatile boolean threadWaiting = false; static final Color blackTransparent = new Color(0,0,0,0); int objectId = -1; // Package scope contructor J3DGraphics2DImpl(Canvas3D c) { canvas3d = c; synchronized (VirtualUniverse.mc.contextCreationLock) { if (c.ctx == null) { // create a dummy bufferImage width = 1; height = 1; g3dImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); offScreenGraphics2D = g3dImage.createGraphics(); } else { init(); } } } // This is invoke from Renderer callback when the first // time createContext() finish which set // canvas3d.extensionSupported correctly. void init() { // if ABGR extension is supported, we want to use // TYPE_4BYTE_ABGR to make a fast copy if (!initCtx) { abgr = ((canvas3d.extensionsSupported & Canvas3D.EXT_ABGR) != 0); width = canvas3d.getWidth(); height = canvas3d.getHeight(); initTexMap = false; if (width <= 0) { width = 1; } if (height <= 0) { height = 1; } synchronized (extentLock) { xmax = width; ymax = height; xmin = 0; ymin = 0; } g3dImage = new BufferedImage(width, height, (abgr ? BufferedImage.TYPE_4BYTE_ABGR: BufferedImage.TYPE_INT_ARGB)); offScreenGraphics2D = g3dImage.createGraphics(); clearOffScreen(); if (!abgr) { data = new byte[width*height*4]; } // should be the last flag to set initCtx = true; } } /** * Flushes all previously executed rendering operations to the * drawing buffer for this 2D graphics object. * * @param wait flag indicating whether or not to wait for the * rendering to be complete before returning from this call. */ public void flush(boolean waiting) { if (hasBeenDisposed) { throw new IllegalStateException(J3dI18N.getString("J3DGraphics2D0")); } if (!isFlushed) { // Composite g3dImage into Canvas3D if (Thread.currentThread() == canvas3d.screen.renderer) { if (!initCtx) { return; } doFlush(); } else { if (!initCtx) { if (waiting && (canvas3d.pendingView != null) && canvas3d.pendingView.activeStatus) { // wait until Renderer init() this context while (!initCtx) { MasterControl.threadYield(); } } else { return; } } // Behavior Scheduler or other threads // XXXX: may not be legal for behaviorScheduler // May cause deadlock if it is in behaviorScheduler // and we wait for Renderer to finish boolean renderRun = (Thread.currentThread() != canvas3d.view.universe.behaviorScheduler); // This must put before sendRenderMessage() threadWaiting = true; sendRenderMessage(renderRun, GraphicsContext3D.FLUSH2D, null, null, null); if (waiting) { // It is possible that thread got notify BEFORE // the following runMonitor invoke. runMonitor(J3dThread.WAIT); } } isFlushed = true; } } // copy the data into a byte buffer that will be passed to opengl void doFlush() { assert !hasBeenDisposed; // clip to offscreen buffer size if (canvas3d.ctx == null) { canvas3d.getGraphicsContext3D().doClear(); } synchronized (extentLock) { if (xmin < 0) { xmin = 0; } if (xmax > width) { xmax = width; } if (ymin < 0) { ymin = 0; } if (ymax > height) { ymax = height; } if ((xmax - xmin > 0) && (ymax - ymin > 0)) { if (abgr) { data = ((DataBufferByte)g3dImage.getRaster().getDataBuffer()).getData(); } else { copyImage(g3dImage, data, width, height, xmin, ymin, xmax, ymax); } copyDataToCanvas(0, 0, xmin, ymin, xmax, ymax, width, height); } else { runMonitor(J3dThread.NOTIFY); } // this define an empty region xmax = 0; ymax = 0; xmin = width; ymin = height; } } // borrowed from ImageComponentRetained since ImageComponent2D // seems to do stuff we don't need to final void copyImage(BufferedImage bi, byte[] image, int width, int height, int x1, int y1, int x2, int y2) { assert !hasBeenDisposed; int biType = bi.getType(); int w, h, i, j; int row, rowBegin, rowInc, dstBegin; dstBegin = 0; rowInc = 1; rowBegin = 0; // convert format to RGBA for underlying OGL use if ((biType == BufferedImage.TYPE_INT_ARGB) || (biType == BufferedImage.TYPE_INT_RGB)) { // optimized cases rowBegin = y1; int colBegin = x1; int[] intData = ((DataBufferInt)bi.getRaster().getDataBuffer()).getData(); int rowOffset = rowInc * width; int intPixel; rowBegin = rowBegin*width + colBegin; dstBegin = rowBegin*4; if (biType == BufferedImage.TYPE_INT_ARGB) { for (h = y1; h < y2; h++) { i = rowBegin; j = dstBegin; for (w = x1; w < x2; w++, i++) { intPixel = intData[i]; image[j++] = (byte)((intPixel >> 16) & 0xff); image[j++] = (byte)((intPixel >> 8) & 0xff); image[j++] = (byte)(intPixel & 0xff); image[j++] = (byte)((intPixel >> 24) & 0xff); } rowBegin += rowOffset; dstBegin += (rowOffset*4); } } else { for (h = y1; h < y2; h++) { i = rowBegin; j = dstBegin; for (w = x1; w < x2; w++, i++) { intPixel = intData[i]; image[j++] = (byte)((intPixel >> 16) & 0xff); image[j++] = (byte)((intPixel >> 8) & 0xff); image[j++] = (byte)(intPixel & 0xff); image[j++] = (byte)255; } rowBegin += rowOffset; dstBegin += (rowOffset*4); } } } else { // non-optimized cases WritableRaster ras = bi.getRaster(); ColorModel cm = bi.getColorModel(); Object pixel = ImageComponentRetained.getDataElementBuffer(ras); j = (y1*width + x1)*4; for (h = y1; h < y2; h++) { i = j; for (w = x1; w < x2; w++) { ras.getDataElements(w, h, pixel); image[j++] = (byte)cm.getRed(pixel); image[j++] = (byte)cm.getGreen(pixel); image[j++] = (byte)cm.getBlue(pixel); image[j++] = (byte)cm.getAlpha(pixel); } j = i+ width*4; } } } void sendRenderMessage(boolean renderRun, int command, Object arg1, Object arg2, Object arg3) { // send a message to the request renderer J3dMessage renderMessage = new J3dMessage(); renderMessage.threads = J3dThread.RENDER_THREAD; renderMessage.type = J3dMessage.RENDER_IMMEDIATE; renderMessage.universe = null; renderMessage.view = null; renderMessage.args[0] = canvas3d; renderMessage.args[1] = new Integer(command); renderMessage.args[2] = arg1; renderMessage.args[3] = arg2; renderMessage.args[4] = arg3; while (!canvas3d.view.inRenderThreadData) { // wait until the renderer thread data in added in // MC:RenderThreadData array ready to receive message MasterControl.threadYield(); } canvas3d.screen.renderer.rendererStructure.addMessage(renderMessage); if (renderRun) { // notify mc that there is work to do VirtualUniverse.mc.sendRunMessage(canvas3d.view, J3dThread.RENDER_THREAD); } else { // notify mc that there is work for the request renderer VirtualUniverse.mc.setWorkForRequestRenderer(); } } final void validate() { validate(0, 0, width, height); } void validate(float x1, float y1, float x2, float y2, AffineTransform xform) { float t; if (xform == null) { validate(x1, y1, x2, y2); } else { ptSrc.x = x1; ptSrc.y = y1; xform.transform(ptSrc, ptDst1); ptSrc.x = x2; ptSrc.y = y2; xform.transform(ptSrc, ptDst2); if (ptDst1.x > ptDst2.x) { t = ptDst1.x; ptDst1.x = ptDst2.x; ptDst2.x = t; } if (ptDst1.y > ptDst2.y) { t = ptDst1.y; ptDst1.y = ptDst2.y; ptDst2.y = t; } // take care of numerical error by adding 1 validate(ptDst1.x-1, ptDst1.y-1, ptDst2.x+1, ptDst2.y+1); } } void validate(float x1, float y1, float x2, float y2) { boolean doResize = false; isFlushed = false; synchronized(canvas3d) { if (initCtx && canvas3d.resizeGraphics2D) { doResize = true; canvas3d.resizeGraphics2D = false; } } if (doResize) { synchronized (VirtualUniverse.mc.contextCreationLock) { Graphics2D oldOffScreenGraphics2D = offScreenGraphics2D; initCtx = false; init(); copyGraphics2D(oldOffScreenGraphics2D); } } else { AffineTransform tr = getTransform(); ptSrc.x = x1; ptSrc.y = y1; tr.transform(ptSrc, ptDst1); ptSrc.x = x2; ptSrc.y = y2; tr.transform(ptSrc, ptDst2); synchronized (extentLock) { if (ptDst1.x < xmin) { xmin = (int) ptDst1.x; } if (ptDst1.y < ymin) { ymin = (int) ptDst1.y; } if (ptDst2.x > xmax) { xmax = (int) ptDst2.x; } if (ptDst2.y > ymax) { ymax = (int) ptDst2.y; } } } } void copyGraphics2D(Graphics2D oldg) { // restore the original setting of Graphics2D when resizing the windows setColor(oldg.getColor()); setFont(oldg.getFont()); setClip(oldg.getClip()); setComposite(oldg.getComposite()); setTransform(oldg.getTransform()); setPaint(oldg.getPaint()); setStroke(oldg.getStroke()); if (xOrModeColor != null) { setXORMode(xOrModeColor); } } // Implementation of Graphics2D methods public final void clip(Shape s) { offScreenGraphics2D.clip(s); } public FontMetrics getFontMetrics() { return offScreenGraphics2D.getFontMetrics(); } public Rectangle getClipBounds(Rectangle r) { return offScreenGraphics2D.getClipBounds(r); } public Rectangle getClipRect() { return offScreenGraphics2D.getClipRect(); } public String toString() { return offScreenGraphics2D.toString(); } public final AffineTransform getTransform() { return offScreenGraphics2D.getTransform(); } public final Color getColor() { return offScreenGraphics2D.getColor(); } public final Composite getComposite() { return offScreenGraphics2D.getComposite(); } public final Font getFont() { return offScreenGraphics2D.getFont(); } public final FontMetrics getFontMetrics(Font f) { return offScreenGraphics2D.getFontMetrics(f); } public final FontRenderContext getFontRenderContext() { return offScreenGraphics2D.getFontRenderContext(); } public final GraphicsConfiguration getDeviceConfiguration() { return offScreenGraphics2D.getDeviceConfiguration(); } public final Object getRenderingHint(Key hintKey) { return offScreenGraphics2D.getRenderingHint(hintKey); } public final Paint getPaint() { return offScreenGraphics2D.getPaint(); } public final Rectangle getClipBounds() { return offScreenGraphics2D.getClipBounds(); } public final RenderingHints getRenderingHints() { return offScreenGraphics2D.getRenderingHints(); } public final Shape getClip() { return offScreenGraphics2D.getClip(); } public final Stroke getStroke() { return offScreenGraphics2D.getStroke(); } public final boolean drawImage(Image img, AffineTransform xform, ImageObserver obs) { validate(0, 0, img.getWidth(obs), img.getHeight(obs), xform); return offScreenGraphics2D.drawImage(img, xform, obs); } public final void drawImage(BufferedImage img, BufferedImageOp op, int x, int y) { if (op != null) { img = op.filter(img, null); } validate(x, y, x+img.getWidth(), y+img.getHeight()); offScreenGraphics2D.drawImage(img, null, x, y); } public final boolean drawImage(Image img, int x, int y, ImageObserver observer) { validate(x, y, x + img.getWidth(observer), y + img.getWidth(observer)); return offScreenGraphics2D.drawImage(img, x, y, observer); } public final boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) { validate(x, y, x+width, y+height); return offScreenGraphics2D.drawImage(img, x, y, width, height, observer); } public final boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) { validate(x, y, x+width, y+height); return offScreenGraphics2D.drawImage(img, x, y, width, height, bgcolor, observer); } public final void drawImage(BufferedImage img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) { validate(dx1, dy1, dx2, dy2); offScreenGraphics2D.drawImage(img, dx1, dy1, dx2, dy2, sx1, sy1, sx2, sy2, observer); } public final boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -