diff options
Diffstat (limited to 'canvas/source/java/JavaCanvas.java')
-rw-r--r-- | canvas/source/java/JavaCanvas.java | 678 |
1 files changed, 678 insertions, 0 deletions
diff --git a/canvas/source/java/JavaCanvas.java b/canvas/source/java/JavaCanvas.java new file mode 100644 index 000000000000..c4090d06ee0f --- /dev/null +++ b/canvas/source/java/JavaCanvas.java @@ -0,0 +1,678 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: JavaCanvas.java,v $ + * $Revision: 1.9 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org 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 Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// UNO +import com.sun.star.uno.XComponentContext; +import com.sun.star.uno.AnyConverter; + +// OOo AWT +import com.sun.star.awt.*; + +// Canvas +import com.sun.star.rendering.*; +import com.sun.star.geometry.*; + +// Java AWT +import java.awt.*; + +public class JavaCanvas + extends CanvasBase + implements com.sun.star.awt.XWindow, + com.sun.star.rendering.XSpriteCanvas, + com.sun.star.rendering.XIntegerBitmap, + com.sun.star.lang.XServiceInfo, + com.sun.star.lang.XInitialization +{ + private WindowAdapter dummyFrame; + public BackBuffer backBuffer; + private java.awt.image.BufferStrategy bufferStrategy; + + private java.awt.Font fpsFont; + private long lastTime; + private com.sun.star.awt.Rectangle boundRect; + + public Graphics2D getGraphics() + { + return backBuffer.getGraphics(); + } + + //---------------------------------------------------------------------------------- + + // + // XInitialization + // =============== + // + public void initialize( java.lang.Object[] arguments ) + { + CanvasUtils.printLog( "JavaCanvas.initialize called!" ); + + // Do that as the very first thing. The Java2D internal + // classes choose their render path at initialization time, + // thus this must happen before doing _any_ GUI. + + // TODO: Put those flags into javarc/java.ini, we're maybe + // coming late into a running JVM! + + // now, we're getting slightly system dependent here. + String os = (String) System.getProperty("os.name"); + + CanvasUtils.printLog( "System detected: " + os ); + + // tweak some speed knobs... +// if( os.startsWith("Windows") ) +// { +// System.setProperty("sun.java2d.translaccel", "true"); +// System.setProperty("sun.java2d.ddforcevram", "true"); +// //System.setProperty("sun.java2d.accthreshold", "0"); + +// CanvasUtils.printLog( "Optimizing for Windows" ); +// } +// else +// { +// System.setProperty("sun.java2d.opengl", "true"); + +// CanvasUtils.printLog( "Optimizing for Unix" ); +// } + + /* we're initialized with the following array of anys: + + arguments[0] = pointer to VCL window + arguments[1] = Integer (operating system window handle) + arguments[2] = com.sun.star.awt.Rectangle (position and size within that OS window) + arguments[3] = boolean (fullsize window or not) + + We then generate a dummy Java frame with that window as the + parent, to fake a root window for the Java implementation. + */ + try + { + boundRect = (com.sun.star.awt.Rectangle) arguments[2]; + + //boolean isFullScreen = arguments[1]; + boolean isFullScreen = true; + //AnyConverter.toBoolean( arguments[3] ) ); + + // fake a root for Java in VCL window. Pass the flag + // whether we shall run fullscreen, too. + dummyFrame = new WindowAdapter( AnyConverter.toInt( arguments[1] ), isFullScreen ); + + if( isFullScreen ) + { + // blow window up to fullscreen. Otherwise, we cannot clear the whole screen, + // which results in ugly flickering + Dimension screenSize = dummyFrame.frame.getToolkit().getScreenSize(); + boundRect.X = 0; + boundRect.Y = 0; + boundRect.Width = screenSize.width-1; + boundRect.Height = screenSize.height-1; + } + + dummyFrame.setPosSize( boundRect.X, boundRect.Y, boundRect.Width, boundRect.Height, (short)0 ); + CanvasUtils.printLog( "Window size: " + boundRect.Width + ", " + boundRect.Height ); + + backBuffer = new BackBuffer( (Graphics2D) dummyFrame.frame.getGraphics(), + Math.max(1,boundRect.Width), + Math.max(1,boundRect.Height) ); + + // TODO: Maybe delay double buffer init until first sprite creation + dummyFrame.frame.createBufferStrategy(2); + bufferStrategy = dummyFrame.frame.getBufferStrategy(); + + if( bufferStrategy.getCapabilities().isPageFlipping() ) + CanvasUtils.printLog( "JavaCanvas.initialize double buffering is using page flipping!" ); + else + CanvasUtils.printLog( "JavaCanvas.initialize double buffering is using blitting!" ); + + lastTime = System.currentTimeMillis(); + fpsFont = new java.awt.Font( "Times", Font.PLAIN, 20 ); + + CanvasUtils.printLog( "JavaCanvas.initialize finished!" ); + } + catch( com.sun.star.lang.IllegalArgumentException e ) + { + CanvasUtils.printLog( "Cannot create EmbeddedFrame within VCL window hierarchy!" ); + } + } + + //---------------------------------------------------------------------------------- + + // + // XComponent + // ========== + // + public void dispose() + { + CanvasUtils.printLog( "JavaCanvas: disposed!" ); + + // destroy all active sprites + java.util.Set entries = activeSprites.entrySet(); + java.util.Iterator iter = entries.iterator(); + + while( iter.hasNext() ) + { + java.util.Map.Entry entry = (java.util.Map.Entry)iter.next(); + if( entry.getValue() != null ) + ((SpriteRep)entry.getValue()).dispose(); + } + + if( bufferStrategy != null ) + bufferStrategy.getDrawGraphics().dispose(); // really necessary? + + if( dummyFrame != null ) + dummyFrame.dispose(); + + if( backBuffer != null) + backBuffer.dispose(); + + bufferStrategy = null; + dummyFrame = null; + backBuffer = null; + + super.dispose(); + } + + //---------------------------------------------------------------------------------- + + public JavaCanvas( XComponentContext xContext ) + { + CanvasUtils.printLog( "JavaCanvas constructor called!" ); + activeSprites = new java.util.HashMap( 33 ); + } + + //---------------------------------------------------------------------------------- + + // + // XWindow interface + // ================= + // + // This is delegated to WindowAdapter! + // + public synchronized void setPosSize( int X, int Y, int Width, int Height, short Flags ) + { + if( dummyFrame != null ) + { + dummyFrame.setPosSize( X, Y, Width, Height, Flags ); + + Width = Math.max(1,Width); + Height= Math.max(1,Height); + + CanvasUtils.printLog( "JavaCanvas graphics set to " + Width + "," + Height ); + backBuffer.setSize(Width,Height); + } + } + + public synchronized com.sun.star.awt.Rectangle getPosSize( ) + { + if( dummyFrame != null ) + return dummyFrame.getPosSize(); + + return new com.sun.star.awt.Rectangle(); + } + + public synchronized void setVisible( boolean visible ) + { + if( dummyFrame != null ) + dummyFrame.setVisible( visible ); + } + + public synchronized void setEnable( boolean enable ) + { + if( dummyFrame != null ) + dummyFrame.setEnable( enable ); + } + + public synchronized void setFocus() + { + if( dummyFrame != null ) + dummyFrame.setFocus(); + } + + public synchronized void addWindowListener( XWindowListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.addWindowListener( xListener ); + } + + public synchronized void removeWindowListener( XWindowListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.removeWindowListener( xListener ); + } + + public synchronized void addFocusListener( XFocusListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.addFocusListener( xListener ); + } + + public synchronized void removeFocusListener( XFocusListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.removeFocusListener( xListener ); + } + + public synchronized void addKeyListener( XKeyListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.addKeyListener( xListener ); + } + + public synchronized void removeKeyListener( XKeyListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.removeKeyListener( xListener ); + } + + public synchronized void addMouseListener( XMouseListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.addMouseListener( xListener ); + } + + public synchronized void removeMouseListener( XMouseListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.removeMouseListener( xListener ); + } + + public synchronized void addMouseMotionListener( XMouseMotionListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.addMouseMotionListener( xListener ); + } + + public synchronized void removeMouseMotionListener( XMouseMotionListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.removeMouseMotionListener( xListener ); + } + + public synchronized void addPaintListener( XPaintListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.addPaintListener( xListener ); + } + + public synchronized void removePaintListener( XPaintListener xListener ) + { + if( dummyFrame != null ) + dummyFrame.removePaintListener( xListener ); + } + + //---------------------------------------------------------------------------------- + + // + // XBitmapCanvas impl + // ================== + // + + public synchronized void copyRect( com.sun.star.rendering.XBitmapCanvas sourceCanvas, + com.sun.star.geometry.RealRectangle2D sourceRect, + com.sun.star.rendering.ViewState sourceViewState, + com.sun.star.rendering.RenderState sourceRenderState, + com.sun.star.geometry.RealRectangle2D destRect, + com.sun.star.rendering.ViewState destViewState, + com.sun.star.rendering.RenderState destRenderState ) + { + CanvasUtils.printLog( "JavaCanvas.copyRect() called" ); + + // TODO: create temp image when transform is non-trivial + + if( sourceCanvas == this ) + { + // copy rectangle within the canvas + getGraphics().copyArea((int)sourceRect.X1, + (int)sourceRect.Y1, + (int)(sourceRect.X2 - sourceRect.X1), + (int)(sourceRect.Y2 - sourceRect.Y1), + (int)(destRect.X1 - sourceRect.X1), + (int)(destRect.Y1 - sourceRect.Y1) ); + } + else + { + if( sourceCanvas instanceof JavaCanvas ) + { + // cache + CanvasUtils.setupGraphicsState( getGraphics(), destViewState, destRenderState, CanvasUtils.alsoSetupPaint ); + + java.awt.Image backBuffer = ((JavaCanvas)sourceCanvas).backBuffer.getBackBuffer(); + + // TODO: really extract correct source rect here + getGraphics().drawImage( backBuffer, 0, 0, null); + CanvasUtils.postRenderImageTreatment( backBuffer ); + } + // TODO: foreign canvas + } + } + + //---------------------------------------------------------------------------------- + + // a map of SpriteReps, with Sprite object as keys. Contains all + // active (i.e. visible) sprites, the SpriteReps are used to + // repaint the sprite content at any time. + private java.util.HashMap activeSprites; + + // + // XSpriteCanvas impl + // ================== + // + + public synchronized com.sun.star.rendering.XAnimatedSprite createSpriteFromAnimation( XAnimation animation ) + { + CanvasUtils.printLog( "JavaCanvas.createSpriteFromAnimation called" ); + + return new CanvasSprite( animation, this, (Graphics2D)dummyFrame.frame.getGraphics() ); + } + + public synchronized XAnimatedSprite createSpriteFromBitmaps( com.sun.star.rendering.XBitmap[] animationBitmaps, + byte interpolationMode ) + { + return null; + } + + public synchronized XCustomSprite createCustomSprite( RealSize2D spriteSize ) + { + CanvasUtils.printLog( "JavaCanvas.createCustomSprite called" ); + + return new CanvasCustomSprite( spriteSize, this, (Graphics2D)dummyFrame.frame.getGraphics() ); + } + + public synchronized XSprite createClonedSprite( XSprite original ) + { + return new CanvasClonedSprite( this, original ); + } + + public synchronized boolean updateScreen( boolean bUpdateAll ) + { + redrawAllLayers(); + + return true; + } + + // + // XBitmap implementation + // ====================== + // + + public synchronized IntegerSize2D getSize() + { + return new IntegerSize2D( boundRect.Width, + boundRect.Height ); + } + + //---------------------------------------------------------------------------------- + + public synchronized XBitmapCanvas queryBitmapCanvas() + { + return this; + } + + //---------------------------------------------------------------------------------- + + public synchronized com.sun.star.rendering.XBitmap getScaledBitmap( RealSize2D newSize, boolean beFast ) throws com.sun.star.lang.IllegalArgumentException, VolatileContentDestroyedException + { + // TODO + return null; + } + + //---------------------------------------------------------------------------------- + + public synchronized boolean hasAlpha() + { + // TODO + return false; + } + + //---------------------------------------------------------------------------------- + + // + // XIntegerBitmap implementation + // ============================= + // + + public synchronized byte[] getData( IntegerBitmapLayout[] bitmapLayout, + IntegerRectangle2D rect ) + { + // TODO + return null; + } + + //---------------------------------------------------------------------------------- + + public synchronized void setData( byte[] data, IntegerBitmapLayout bitmapLayout, com.sun.star.geometry.IntegerRectangle2D rect ) + { + // TODO + } + + //---------------------------------------------------------------------------------- + + public synchronized void setPixel( byte[] color, IntegerBitmapLayout bitmapLayout, com.sun.star.geometry.IntegerPoint2D pos ) + { + // TODO + } + + //---------------------------------------------------------------------------------- + + public synchronized byte[] getPixel( IntegerBitmapLayout[] bitmapLayout, + IntegerPoint2D pos ) + { + // TODO + return null; + } + + //---------------------------------------------------------------------------------- + + public synchronized XBitmapPalette getPalette() + { + // TODO + return null; + } + + //---------------------------------------------------------------------------------- + + public synchronized IntegerBitmapLayout getMemoryLayout() + { + // TODO: finish that one + IntegerBitmapLayout layout = new IntegerBitmapLayout(); + + return layout; + } + + //---------------------------------------------------------------------------------- + + // + // XSpriteCanvas helper + // ==================== + // + public synchronized void renderAnimation( CanvasSprite sprite, XAnimation animation, double t ) + { + SpriteRep spriteRep = (SpriteRep)activeSprites.get( sprite ); + if( spriteRep != null ) + { + //Graphics2D graph = getWindowGraphics(); + + // TODO: ensure update of graphics object externally, e.g. when + // VCL moves the toplevel window. + //java.awt.Rectangle bounds = dummyFrame.frame.getBounds(); + //graphics.setGraphics(graph, bounds.width, bounds.height); + + spriteRep.renderAnimation( animation, sprite.getViewState(), t ); + } + else + { + CanvasUtils.printLog( "JavaCanvas.renderAnimation sprite not active!" ); + } + } + + public synchronized void showSprite( SpriteBase sprite ) + { + CanvasUtils.printLog( "JavaCanvas.showSprite() called" ); + + SpriteRep spriteRep = (SpriteRep)activeSprites.get( sprite ); + if( spriteRep != null ) + { + CanvasUtils.printLog( "JavaCanvas.showSprite sprite already active!" ); + } + else + { + spriteRep = sprite.getSpriteRep(); + + // a valid SpriteRep for a given Sprite in the + // activeSprites hash denotes 'sprite active' + activeSprites.put( sprite, spriteRep ); + + // TODO: TEMP! Just for testing! Set empty cursor for presentation +// dummyFrame.frame.setCursor( dummyFrame.frame.getToolkit().createCustomCursor(new java.awt.image.BufferedImage(0,0, +// java.awt.image.BufferedImage.TYPE_INT_RGB), +// new java.awt.Point(0,0), +// "") ); + } + } + + public synchronized void hideSprite( SpriteBase sprite ) + { + CanvasUtils.printLog( "JavaCanvas.hideSprite() called" ); + + SpriteRep spriteRep = (SpriteRep)activeSprites.get( sprite ); + if( spriteRep != null ) + { + activeSprites.put( sprite, null ); + redrawAllLayers(); + } + else + { + CanvasUtils.printLog( "JavaCanvas.hideSprite sprite not active!" ); + } + } + + private void redrawAllLayers() + { + // fetch the Graphics object to draw into (we're doing double + // buffering here, the content is later shown via + // bufferStrategy.show(). + Graphics2D graph = null; + + try + { + graph = (Graphics2D)bufferStrategy.getDrawGraphics(); + + GraphicsDevice device = graph.getDeviceConfiguration().getDevice(); + CanvasUtils.printLog( "Available vram: " + device.getAvailableAcceleratedMemory() ); + + // repaint background + backBuffer.redraw( graph ); + + // repaint all active sprites + java.util.Set entries = activeSprites.entrySet(); + java.util.Iterator iter = entries.iterator(); + while( iter.hasNext() ) + { + java.util.Map.Entry entry = (java.util.Map.Entry)iter.next(); + if( entry.getValue() != null ) + ((SpriteRep)entry.getValue()).redraw(graph); + } + + long currTime = System.currentTimeMillis(); + graph.setComposite( AlphaComposite.getInstance(AlphaComposite.SRC_OVER) ); + graph.setFont( fpsFont ); + graph.setColor( java.awt.Color.black ); + + try + { + String fps = new String( String.valueOf(1000.0/(currTime-lastTime)) ); + graph.drawString( fps.substring(0,5) + " fps", 0, 20); + CanvasUtils.printLog( fps.substring(0,5) + " fps" ); + } + catch( Exception e ) + { + graph.drawString( "0 fps", 0, 20); + } + + lastTime = currTime; + } + catch( Exception e ) + { + CanvasUtils.printLog( "Exception thrown in redrawAllLayers" ); + } + finally + { + if( graph != null ) + graph.dispose(); + } + + bufferStrategy.show(); + } + + //---------------------------------------------------------------------------------- + + private static final String s_implName = "XCanvas.java.impl"; + private static final String s_serviceName = "com.sun.star.rendering.JavaCanvas"; + + //---------------------------------------------------------------------------------- + + // + // XServiceInfo impl + // ================= + // + public synchronized String getImplementationName() + { + return s_implName; + } + + public synchronized String [] getSupportedServiceNames() + { + return new String [] { s_serviceName }; + } + + public synchronized boolean supportsService( String serviceName ) + { + return serviceName.equals( s_serviceName ); + } + + public static com.sun.star.lang.XSingleServiceFactory __getServiceFactory( + String implName, + com.sun.star.lang.XMultiServiceFactory multiFactory, + com.sun.star.registry.XRegistryKey regKey ) + { + if (implName.equals( s_implName )) + { + return com.sun.star.comp.loader.FactoryHelper.getServiceFactory( + JavaCanvas.class, s_serviceName, multiFactory, regKey ); + } + return null; + } + + public static boolean __writeRegistryServiceInfo( + com.sun.star.registry.XRegistryKey regKey ) + { + return com.sun.star.comp.loader.FactoryHelper.writeRegistryServiceInfo( + s_implName, s_serviceName, regKey ); + } +} |