1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: JavaCanvas.java,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 import com
.sun
.star
.uno
.XComponentContext
;
33 import com
.sun
.star
.uno
.AnyConverter
;
36 import com
.sun
.star
.awt
.*;
39 import com
.sun
.star
.rendering
.*;
40 import com
.sun
.star
.geometry
.*;
45 public class JavaCanvas
47 implements com
.sun
.star
.awt
.XWindow
,
48 com
.sun
.star
.rendering
.XSpriteCanvas
,
49 com
.sun
.star
.rendering
.XIntegerBitmap
,
50 com
.sun
.star
.lang
.XServiceInfo
,
51 com
.sun
.star
.lang
.XInitialization
53 private WindowAdapter dummyFrame
;
54 public BackBuffer backBuffer
;
55 private java
.awt
.image
.BufferStrategy bufferStrategy
;
57 private java
.awt
.Font fpsFont
;
58 private long lastTime
;
59 private com
.sun
.star
.awt
.Rectangle boundRect
;
61 public Graphics2D
getGraphics()
63 return backBuffer
.getGraphics();
66 //----------------------------------------------------------------------------------
72 public void initialize( java
.lang
.Object
[] arguments
)
74 CanvasUtils
.printLog( "JavaCanvas.initialize called!" );
76 // Do that as the very first thing. The Java2D internal
77 // classes choose their render path at initialization time,
78 // thus this must happen before doing _any_ GUI.
80 // TODO: Put those flags into javarc/java.ini, we're maybe
81 // coming late into a running JVM!
83 // now, we're getting slightly system dependent here.
84 String os
= (String
) System
.getProperty("os.name");
86 CanvasUtils
.printLog( "System detected: " + os
);
88 // tweak some speed knobs...
89 // if( os.startsWith("Windows") )
91 // System.setProperty("sun.java2d.translaccel", "true");
92 // System.setProperty("sun.java2d.ddforcevram", "true");
93 // //System.setProperty("sun.java2d.accthreshold", "0");
95 // CanvasUtils.printLog( "Optimizing for Windows" );
99 // System.setProperty("sun.java2d.opengl", "true");
101 // CanvasUtils.printLog( "Optimizing for Unix" );
104 /* we're initialized with the following array of anys:
106 arguments[0] = pointer to VCL window
107 arguments[1] = Integer (operating system window handle)
108 arguments[2] = com.sun.star.awt.Rectangle (position and size within that OS window)
109 arguments[3] = boolean (fullsize window or not)
111 We then generate a dummy Java frame with that window as the
112 parent, to fake a root window for the Java implementation.
116 boundRect
= (com
.sun
.star
.awt
.Rectangle
) arguments
[2];
118 //boolean isFullScreen = arguments[1];
119 boolean isFullScreen
= true;
120 //AnyConverter.toBoolean( arguments[3] ) );
122 // fake a root for Java in VCL window. Pass the flag
123 // whether we shall run fullscreen, too.
124 dummyFrame
= new WindowAdapter( AnyConverter
.toInt( arguments
[1] ), isFullScreen
);
128 // blow window up to fullscreen. Otherwise, we cannot clear the whole screen,
129 // which results in ugly flickering
130 Dimension screenSize
= dummyFrame
.frame
.getToolkit().getScreenSize();
133 boundRect
.Width
= screenSize
.width
-1;
134 boundRect
.Height
= screenSize
.height
-1;
137 dummyFrame
.setPosSize( boundRect
.X
, boundRect
.Y
, boundRect
.Width
, boundRect
.Height
, (short)0 );
138 CanvasUtils
.printLog( "Window size: " + boundRect
.Width
+ ", " + boundRect
.Height
);
140 backBuffer
= new BackBuffer( (Graphics2D
) dummyFrame
.frame
.getGraphics(),
141 Math
.max(1,boundRect
.Width
),
142 Math
.max(1,boundRect
.Height
) );
144 // TODO: Maybe delay double buffer init until first sprite creation
145 dummyFrame
.frame
.createBufferStrategy(2);
146 bufferStrategy
= dummyFrame
.frame
.getBufferStrategy();
148 if( bufferStrategy
.getCapabilities().isPageFlipping() )
149 CanvasUtils
.printLog( "JavaCanvas.initialize double buffering is using page flipping!" );
151 CanvasUtils
.printLog( "JavaCanvas.initialize double buffering is using blitting!" );
153 lastTime
= System
.currentTimeMillis();
154 fpsFont
= new java
.awt
.Font( "Times", Font
.PLAIN
, 20 );
156 CanvasUtils
.printLog( "JavaCanvas.initialize finished!" );
158 catch( com
.sun
.star
.lang
.IllegalArgumentException e
)
160 CanvasUtils
.printLog( "Cannot create EmbeddedFrame within VCL window hierarchy!" );
164 //----------------------------------------------------------------------------------
170 public void dispose()
172 CanvasUtils
.printLog( "JavaCanvas: disposed!" );
174 // destroy all active sprites
175 java
.util
.Set entries
= activeSprites
.entrySet();
176 java
.util
.Iterator iter
= entries
.iterator();
178 while( iter
.hasNext() )
180 java
.util
.Map
.Entry entry
= (java
.util
.Map
.Entry
)iter
.next();
181 if( entry
.getValue() != null )
182 ((SpriteRep
)entry
.getValue()).dispose();
185 if( bufferStrategy
!= null )
186 bufferStrategy
.getDrawGraphics().dispose(); // really necessary?
188 if( dummyFrame
!= null )
189 dummyFrame
.dispose();
191 if( backBuffer
!= null)
192 backBuffer
.dispose();
194 bufferStrategy
= null;
201 //----------------------------------------------------------------------------------
203 public JavaCanvas( XComponentContext xContext
)
205 CanvasUtils
.printLog( "JavaCanvas constructor called!" );
206 activeSprites
= new java
.util
.HashMap( 33 );
209 //----------------------------------------------------------------------------------
215 // This is delegated to WindowAdapter!
217 public synchronized void setPosSize( int X
, int Y
, int Width
, int Height
, short Flags
)
219 if( dummyFrame
!= null )
221 dummyFrame
.setPosSize( X
, Y
, Width
, Height
, Flags
);
223 Width
= Math
.max(1,Width
);
224 Height
= Math
.max(1,Height
);
226 CanvasUtils
.printLog( "JavaCanvas graphics set to " + Width
+ "," + Height
);
227 backBuffer
.setSize(Width
,Height
);
231 public synchronized com
.sun
.star
.awt
.Rectangle
getPosSize( )
233 if( dummyFrame
!= null )
234 return dummyFrame
.getPosSize();
236 return new com
.sun
.star
.awt
.Rectangle();
239 public synchronized void setVisible( boolean visible
)
241 if( dummyFrame
!= null )
242 dummyFrame
.setVisible( visible
);
245 public synchronized void setEnable( boolean enable
)
247 if( dummyFrame
!= null )
248 dummyFrame
.setEnable( enable
);
251 public synchronized void setFocus()
253 if( dummyFrame
!= null )
254 dummyFrame
.setFocus();
257 public synchronized void addWindowListener( XWindowListener xListener
)
259 if( dummyFrame
!= null )
260 dummyFrame
.addWindowListener( xListener
);
263 public synchronized void removeWindowListener( XWindowListener xListener
)
265 if( dummyFrame
!= null )
266 dummyFrame
.removeWindowListener( xListener
);
269 public synchronized void addFocusListener( XFocusListener xListener
)
271 if( dummyFrame
!= null )
272 dummyFrame
.addFocusListener( xListener
);
275 public synchronized void removeFocusListener( XFocusListener xListener
)
277 if( dummyFrame
!= null )
278 dummyFrame
.removeFocusListener( xListener
);
281 public synchronized void addKeyListener( XKeyListener xListener
)
283 if( dummyFrame
!= null )
284 dummyFrame
.addKeyListener( xListener
);
287 public synchronized void removeKeyListener( XKeyListener xListener
)
289 if( dummyFrame
!= null )
290 dummyFrame
.removeKeyListener( xListener
);
293 public synchronized void addMouseListener( XMouseListener xListener
)
295 if( dummyFrame
!= null )
296 dummyFrame
.addMouseListener( xListener
);
299 public synchronized void removeMouseListener( XMouseListener xListener
)
301 if( dummyFrame
!= null )
302 dummyFrame
.removeMouseListener( xListener
);
305 public synchronized void addMouseMotionListener( XMouseMotionListener xListener
)
307 if( dummyFrame
!= null )
308 dummyFrame
.addMouseMotionListener( xListener
);
311 public synchronized void removeMouseMotionListener( XMouseMotionListener xListener
)
313 if( dummyFrame
!= null )
314 dummyFrame
.removeMouseMotionListener( xListener
);
317 public synchronized void addPaintListener( XPaintListener xListener
)
319 if( dummyFrame
!= null )
320 dummyFrame
.addPaintListener( xListener
);
323 public synchronized void removePaintListener( XPaintListener xListener
)
325 if( dummyFrame
!= null )
326 dummyFrame
.removePaintListener( xListener
);
329 //----------------------------------------------------------------------------------
332 // XBitmapCanvas impl
333 // ==================
336 public synchronized void copyRect( com
.sun
.star
.rendering
.XBitmapCanvas sourceCanvas
,
337 com
.sun
.star
.geometry
.RealRectangle2D sourceRect
,
338 com
.sun
.star
.rendering
.ViewState sourceViewState
,
339 com
.sun
.star
.rendering
.RenderState sourceRenderState
,
340 com
.sun
.star
.geometry
.RealRectangle2D destRect
,
341 com
.sun
.star
.rendering
.ViewState destViewState
,
342 com
.sun
.star
.rendering
.RenderState destRenderState
)
344 CanvasUtils
.printLog( "JavaCanvas.copyRect() called" );
346 // TODO: create temp image when transform is non-trivial
348 if( sourceCanvas
== this )
350 // copy rectangle within the canvas
351 getGraphics().copyArea((int)sourceRect
.X1
,
353 (int)(sourceRect
.X2
- sourceRect
.X1
),
354 (int)(sourceRect
.Y2
- sourceRect
.Y1
),
355 (int)(destRect
.X1
- sourceRect
.X1
),
356 (int)(destRect
.Y1
- sourceRect
.Y1
) );
360 if( sourceCanvas
instanceof JavaCanvas
)
363 CanvasUtils
.setupGraphicsState( getGraphics(), destViewState
, destRenderState
, CanvasUtils
.alsoSetupPaint
);
365 java
.awt
.Image backBuffer
= ((JavaCanvas
)sourceCanvas
).backBuffer
.getBackBuffer();
367 // TODO: really extract correct source rect here
368 getGraphics().drawImage( backBuffer
, 0, 0, null);
369 CanvasUtils
.postRenderImageTreatment( backBuffer
);
371 // TODO: foreign canvas
375 //----------------------------------------------------------------------------------
377 // a map of SpriteReps, with Sprite object as keys. Contains all
378 // active (i.e. visible) sprites, the SpriteReps are used to
379 // repaint the sprite content at any time.
380 private java
.util
.HashMap activeSprites
;
383 // XSpriteCanvas impl
384 // ==================
387 public synchronized com
.sun
.star
.rendering
.XAnimatedSprite
createSpriteFromAnimation( XAnimation animation
)
389 CanvasUtils
.printLog( "JavaCanvas.createSpriteFromAnimation called" );
391 return new CanvasSprite( animation
, this, (Graphics2D
)dummyFrame
.frame
.getGraphics() );
394 public synchronized XAnimatedSprite
createSpriteFromBitmaps( com
.sun
.star
.rendering
.XBitmap
[] animationBitmaps
,
395 byte interpolationMode
)
400 public synchronized XCustomSprite
createCustomSprite( RealSize2D spriteSize
)
402 CanvasUtils
.printLog( "JavaCanvas.createCustomSprite called" );
404 return new CanvasCustomSprite( spriteSize
, this, (Graphics2D
)dummyFrame
.frame
.getGraphics() );
407 public synchronized XSprite
createClonedSprite( XSprite original
)
409 return new CanvasClonedSprite( this, original
);
412 public synchronized boolean updateScreen( boolean bUpdateAll
)
420 // XBitmap implementation
421 // ======================
424 public synchronized IntegerSize2D
getSize()
426 return new IntegerSize2D( boundRect
.Width
,
430 //----------------------------------------------------------------------------------
432 public synchronized XBitmapCanvas
queryBitmapCanvas()
437 //----------------------------------------------------------------------------------
439 public synchronized com
.sun
.star
.rendering
.XBitmap
getScaledBitmap( RealSize2D newSize
, boolean beFast
) throws com
.sun
.star
.lang
.IllegalArgumentException
, VolatileContentDestroyedException
445 //----------------------------------------------------------------------------------
447 public synchronized boolean hasAlpha()
453 //----------------------------------------------------------------------------------
456 // XIntegerBitmap implementation
457 // =============================
460 public synchronized byte[] getData( IntegerBitmapLayout
[] bitmapLayout
,
461 IntegerRectangle2D rect
)
467 //----------------------------------------------------------------------------------
469 public synchronized void setData( byte[] data
, IntegerBitmapLayout bitmapLayout
, com
.sun
.star
.geometry
.IntegerRectangle2D rect
)
474 //----------------------------------------------------------------------------------
476 public synchronized void setPixel( byte[] color
, IntegerBitmapLayout bitmapLayout
, com
.sun
.star
.geometry
.IntegerPoint2D pos
)
481 //----------------------------------------------------------------------------------
483 public synchronized byte[] getPixel( IntegerBitmapLayout
[] bitmapLayout
,
490 //----------------------------------------------------------------------------------
492 public synchronized XBitmapPalette
getPalette()
498 //----------------------------------------------------------------------------------
500 public synchronized IntegerBitmapLayout
getMemoryLayout()
502 // TODO: finish that one
503 IntegerBitmapLayout layout
= new IntegerBitmapLayout();
508 //----------------------------------------------------------------------------------
511 // XSpriteCanvas helper
512 // ====================
514 public synchronized void renderAnimation( CanvasSprite sprite
, XAnimation animation
, double t
)
516 SpriteRep spriteRep
= (SpriteRep
)activeSprites
.get( sprite
);
517 if( spriteRep
!= null )
519 //Graphics2D graph = getWindowGraphics();
521 // TODO: ensure update of graphics object externally, e.g. when
522 // VCL moves the toplevel window.
523 //java.awt.Rectangle bounds = dummyFrame.frame.getBounds();
524 //graphics.setGraphics(graph, bounds.width, bounds.height);
526 spriteRep
.renderAnimation( animation
, sprite
.getViewState(), t
);
530 CanvasUtils
.printLog( "JavaCanvas.renderAnimation sprite not active!" );
534 public synchronized void showSprite( SpriteBase sprite
)
536 CanvasUtils
.printLog( "JavaCanvas.showSprite() called" );
538 SpriteRep spriteRep
= (SpriteRep
)activeSprites
.get( sprite
);
539 if( spriteRep
!= null )
541 CanvasUtils
.printLog( "JavaCanvas.showSprite sprite already active!" );
545 spriteRep
= sprite
.getSpriteRep();
547 // a valid SpriteRep for a given Sprite in the
548 // activeSprites hash denotes 'sprite active'
549 activeSprites
.put( sprite
, spriteRep
);
551 // TODO: TEMP! Just for testing! Set empty cursor for presentation
552 // dummyFrame.frame.setCursor( dummyFrame.frame.getToolkit().createCustomCursor(new java.awt.image.BufferedImage(0,0,
553 // java.awt.image.BufferedImage.TYPE_INT_RGB),
554 // new java.awt.Point(0,0),
559 public synchronized void hideSprite( SpriteBase sprite
)
561 CanvasUtils
.printLog( "JavaCanvas.hideSprite() called" );
563 SpriteRep spriteRep
= (SpriteRep
)activeSprites
.get( sprite
);
564 if( spriteRep
!= null )
566 activeSprites
.put( sprite
, null );
571 CanvasUtils
.printLog( "JavaCanvas.hideSprite sprite not active!" );
575 private void redrawAllLayers()
577 // fetch the Graphics object to draw into (we're doing double
578 // buffering here, the content is later shown via
579 // bufferStrategy.show().
580 Graphics2D graph
= null;
584 graph
= (Graphics2D
)bufferStrategy
.getDrawGraphics();
586 GraphicsDevice device
= graph
.getDeviceConfiguration().getDevice();
587 CanvasUtils
.printLog( "Available vram: " + device
.getAvailableAcceleratedMemory() );
589 // repaint background
590 backBuffer
.redraw( graph
);
592 // repaint all active sprites
593 java
.util
.Set entries
= activeSprites
.entrySet();
594 java
.util
.Iterator iter
= entries
.iterator();
595 while( iter
.hasNext() )
597 java
.util
.Map
.Entry entry
= (java
.util
.Map
.Entry
)iter
.next();
598 if( entry
.getValue() != null )
599 ((SpriteRep
)entry
.getValue()).redraw(graph
);
602 long currTime
= System
.currentTimeMillis();
603 graph
.setComposite( AlphaComposite
.getInstance(AlphaComposite
.SRC_OVER
) );
604 graph
.setFont( fpsFont
);
605 graph
.setColor( java
.awt
.Color
.black
);
609 String fps
= new String( String
.valueOf(1000.0/(currTime
-lastTime
)) );
610 graph
.drawString( fps
.substring(0,5) + " fps", 0, 20);
611 CanvasUtils
.printLog( fps
.substring(0,5) + " fps" );
615 graph
.drawString( "0 fps", 0, 20);
622 CanvasUtils
.printLog( "Exception thrown in redrawAllLayers" );
630 bufferStrategy
.show();
633 //----------------------------------------------------------------------------------
635 private static final String s_implName
= "XCanvas.java.impl";
636 private static final String s_serviceName
= "com.sun.star.rendering.JavaCanvas";
638 //----------------------------------------------------------------------------------
644 public synchronized String
getImplementationName()
649 public synchronized String
[] getSupportedServiceNames()
651 return new String
[] { s_serviceName
};
654 public synchronized boolean supportsService( String serviceName
)
656 return serviceName
.equals( s_serviceName
);
659 public static com
.sun
.star
.lang
.XSingleServiceFactory
__getServiceFactory(
661 com
.sun
.star
.lang
.XMultiServiceFactory multiFactory
,
662 com
.sun
.star
.registry
.XRegistryKey regKey
)
664 if (implName
.equals( s_implName
))
666 return com
.sun
.star
.comp
.loader
.FactoryHelper
.getServiceFactory(
667 JavaCanvas
.class, s_serviceName
, multiFactory
, regKey
);
672 public static boolean __writeRegistryServiceInfo(
673 com
.sun
.star
.registry
.XRegistryKey regKey
)
675 return com
.sun
.star
.comp
.loader
.FactoryHelper
.writeRegistryServiceInfo(
676 s_implName
, s_serviceName
, regKey
);