DrawingSupport.cs :  » Network-Clients » VNC-Client » DrawingSupport » C# / CSharp Open Source

Home
C# / CSharp Open Source
1.2.6.4 mono .net core
2.2.6.4 mono core
3.Aspect Oriented Frameworks
4.Bloggers
5.Build Systems
6.Business Application
7.Charting Reporting Tools
8.Chat Servers
9.Code Coverage Tools
10.Content Management Systems CMS
11.CRM ERP
12.Database
13.Development
14.Email
15.Forum
16.Game
17.GIS
18.GUI
19.IDEs
20.Installers Generators
21.Inversion of Control Dependency Injection
22.Issue Tracking
23.Logging Tools
24.Message
25.Mobile
26.Network Clients
27.Network Servers
28.Office
29.PDF
30.Persistence Frameworks
31.Portals
32.Profilers
33.Project Management
34.RSS RDF
35.Rule Engines
36.Script
37.Search Engines
38.Sound Audio
39.Source Control
40.SQL Clients
41.Template Engines
42.Testing
43.UML
44.Web Frameworks
45.Web Service
46.Web Testing
47.Wiki Engines
48.Windows Presentation Foundation
49.Workflows
50.XML Parsers
C# / C Sharp
C# / C Sharp by API
C# / CSharp Tutorial
C# / CSharp Open Source » Network Clients » VNC Client 
VNC Client » DrawingSupport » DrawingSupport.cs
using System.Windows.Forms;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using System.Threading;
using VNC.RFBDrawing;
using VNC.RFBDrawing.PixelDecoders;
using System.Collections;
using DirectXLIB;

// author: Dominic Ullmann, dominic_ullmann@swissonline.ch
// Version: 1.02
  
// VNC-Client for .NET
// Copyright (C) 2002  Dominic Ullmann

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program 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 for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  


// this namespace contains classes that support drawing. This classes make the code
// in the RFB-Surface independent of the used Graphics libary
namespace DrawingSupport{


  // ***************************************************************************************/  
  // ************************************** Abstract Classes *******************************/
  // ***************************************************************************************/  
  
  /// <summary>
  ///  the DrawSupport class is the main class used by the RFB-Surface to access the 
  /// drawing functionality
  /// </summary>
  public abstract class DrawSupport {
    /// <summary> the pixelformat of the remote framebuffer</summary>
    protected PixelFormat format;
    /// <summary> the width of the remote framebuffer</summary>
    protected int width;
    /// <summary> the height of the remote framebuffer</summary>
    protected int height;
    /// <summary> the depth of the remote framebuffer</summary>
    protected int depth;
    /// <summary> the views using this drawsupport instance </summary>
    protected Hashtable views = new Hashtable();
    /// <summary> is dispose already called </summary>
    protected bool disposed = false;
    
    /// <summary> register a view, which this Drawsupport instance draws to. In this step the view is prepared for drawing to it</summary>
    public abstract void registerView(RFBView view);
    
    /// <summary> initalizies the Drawsupport </summary>
    protected abstract void initalize(PixelFormat format, int width, int height, int depth);
    /// <summary> draws the specified region of backbuffer to screen </summary>
    public abstract void drawBackBufferToScreen(RFBView screen, Rectangle region);
    /// <summary> draws the whole backbuffer to screen </summary>
    public abstract void drawBackBufferToScreen(RFBView screen);
    /// <summary> get Drawing object for updating the backbuffer </summary>
    /// <param name="x">the x coordinate of the drawing region</param>
    /// <param name="y">the y coordinate of the drawing region</param>
    /// <param name="width">the width of the drawing region</param>
    /// <param name="height">the height of the drawing region</param>      
    public abstract DrawingObject getDrawingObject(int x, int y, int width, int height);
    /// <summary> get an offscreenbuffer with the given dimension </summary>
    public abstract OffScreenBuffer getOffScreenBuffer(int width, int height);
    /// <summary> creates an offscreenbuffer with a part of the backbuffer as contents  </summary>    
    public abstract OffScreenBuffer copyFromBackBuffer(int srcX, int srcY, int width, int height);
    
    /// <summary> called by a drawing-Object to inform drawsupport of a performed update.
    /// Should only be called by a drawing-Object created by the getDrawingObject method
    /// </summary>
    protected internal abstract void drawingObjectDone(int x, int y, int width, int height);
    
    /// <summary> for freeing resources, call if drawing support object is no longer needed,
    /// (is otherwise called during finalization)
    /// </summary>
    public abstract void Dispose();
    /// <summary> finalizer </summary>
    ~DrawSupport() {
      if (!disposed) { Dispose(); }
    }
    
  }
  
  
  /// <summary>
  /// provides functionality to draw to a buffer / to the screen.
  /// </summary>
  /// <remarks>  
  /// This class is a general Implementation of DrawingObject, usable with many DrawingSupport classes   
  /// </remarks>  
  public class DrawingObject {
    private int width;
    private int height;
    private int x;
    private int y;
    private OffScreenBuffer backBuffer;
    private DrawSupport draw;

    /// <summary> the width of the region this drawing object represents </summary>
    public int Width { get { return width; } }
    /// <summary> the height of the region this drawing object represents </summary>    
    public int Height { get  { return height; } }
    /// <summary> the x-coordinate of the top-left corner of the region this drawing object represents </summary>    
    public int X { get { return x; } }
    /// <summary> the y-coordinate of the top-left corner of the region this drawing object represents </summary>    
    public int Y { get  { return y; } }
    
    /// <summary>
    /// creates a drawing object, for drawing to a specified region
    /// </summary>
    /// <remarks>
    /// this constructor should only be used from methods/constructors within a drawing-Support class
    /// </remarks>
    /// <param name="x">the x-coordinate of the top-left corner of the drawing region</param>
    /// <param name="y">the y-coordinate of the top-left corner of the drawing region</param>
    /// <param name="width">the width of the drawing region</param>
    /// <param name="height">the height of the drawing region</param>            
    /// <param name="buffer">the backbuffer used during drawing</param>
    /// <param name="drawSup">the drawSupport instance used for drawing</param>
    /// <seealso cref="DrawSupport"/>
    public DrawingObject(int x, int y, int width, int height, OffScreenBuffer buffer, DrawSupport drawSup) {
      this.x = x;
      this.y = y;
      this.width = width;
      this.height = height;
      this.backBuffer = buffer;
      this.draw = drawSup;
    }
    /// <summary> this methods draws a filled rectangle in the specified color and with
    /// the specified size at the specified position 
    /// </summary>
    public virtual void drawFilledRectangle(Color color, int x, int y, int width, int height) {
      backBuffer.drawFilledRectangle(color, this.x + x,this.y + y, width, height);
    }
    
    /// <summary> draw from the contents of an offscreen buffer </summary>
    public virtual void drawOffScreenBuffer(OffScreenBuffer src, int destX, int destY) {
      backBuffer.drawOffScreenBuffer(src, this.x + destX, this.y + destY);
    }
    
    /// <summary> this methods draws data from a byte array. </summary>
    /// <param name="data">the byte array containting the pixel data</param>
    /// <param name="width">the width of the pixeldata in pixel</param>
    /// <param name="height">the height of the pixeldata in pixel</param>
    /// <param name="destX">x-coordinate of the top-left corner of the region, where the pixeldata should be placed to</param>
    /// <param name="destY">y-coordinate of the top-left corner of the region, where the pixeldata should be placed to</param>
    /// <param name="usedDecoder">the usedDecoder parameter specifies the decoder used to produce data in the byte array, must not be null</param>
    public virtual void drawFromByteArray(byte[] data, int width, int height, int destX, int destY, PixelDecoder usedDecoder) {
      backBuffer.drawFromByteArray(data, width, height, this.x + destX, this.y + destY, usedDecoder);
    }
    
    /// <summary> calling this to tell update is done, forcing the changes made with this
    /// drawing object to appear </summary>
    public virtual void updateDone() {
      draw.drawingObjectDone(x, y, width, height);
    }
    
  }

  
  /// <summary>
  /// a buffer for buffering bitmap-data
  /// </summary>
  public interface OffScreenBuffer {
    /// <summary> the widht of the OffscreenBuffer </summary>
    int Width { get; }
    /// <summary> the height of the OffscreenBuffer </summary>    
    int Height { get; }
    
    /// <summary> draw a filled rectangle to the OffscreenBuffer </summary>
    void drawFilledRectangle(Color color, int x, int y, int width, int height);
    /// <summary> draw the contents of another Offscreenbuffer to the OffscreenBuffer </summary>
    void drawOffScreenBuffer(OffScreenBuffer src, int destX, int destY); 
    /// <summary> draw the contents of another Offscreenbuffer to the OffscreenBuffer </summary>
    void drawOffScreenBuffer(OffScreenBuffer src, int destX, int destY, int width, int height, int srcX, int srcY);
    /// <summary> draw text to the OffScreenBuffer </summary>
    void drawText(string text, int x, int y, Font font, Color color);
    /// <summary> draw the data from a byte array to the OffScreenBuffer </summary>
    /// <param name="data">the byte array containting the pixel data</param>
    /// <param name="width">the width of the pixeldata in pixel</param>
    /// <param name="height">the height of the pixeldata in pixel</param>
    /// <param name="destX">x-coordinate of the top-left corner of the region, where the pixeldata should be placed to</param>
    /// <param name="destY">y-coordinate of the top-left corner of the region, where the pixeldata should be placed to</param>
    /// <param name="usedDecoder">the usedDecoder parameter specifies the decoder used to produce data, must not be null</param>
    void drawFromByteArray(byte[] data, int width, int height, int destX, int destY, PixelDecoder usedDecoder);
    /// <summary> disposes resources allocated by offscreenbuffer </summary>
    void Dispose();
  }

  // ***************************************************************************************/  
  // ************************************** DirectX-Implementation *************************/
  // ***************************************************************************************/  

  /// <summary>
  /// this class provides an implmentation of Drawsupport using DirectX
  /// </summary>
  public class DirectXDrawSupport : DrawSupport {
    
    private DirectDraw ddraw;
    private DirectXOffScreenBuffer backBuffer = null;
    private DirectDrawSurface primarySurface = null;
    private RFBSurface surface;
    
    /// <summary> constructor for DirectXDrawSupport </summary>
    /// <param name="surface">the RFBSurface using this drawsupport instance for drawing, needed to reget the pixel-data if content DirectDraw surface is lost</param>
    /// <param name="format">the pixelformat of the remote framebuffer</param>
    /// <param name="width">the width of the remote framebuffer</param>
    /// <param name="height">the height of the remote framebuffer</param>
    /// <param name="depth"></param>      
    public DirectXDrawSupport(PixelFormat format, int width, int height, int depth, RFBSurface surface) {
      initalize(format,width,height,depth);
      
      // initalize direct Draw
      DirectX dx = new DirectX();
      ddraw = dx.createDirectDraw7();  
      this.surface = surface;
    }

    private void createBackBuffer() {
      // must be created after setCooperativeLevel is called
      // backbuffer:
      STRUCT_DDSURFACEDESC2 backBufferDescription = new STRUCT_DDSURFACEDESC2();
      backBufferDescription.flags = CONST_DDSURFACEDESCFLAGS.DdSD_CAPS | CONST_DDSURFACEDESCFLAGS.DdSD_WIDTH | CONST_DDSURFACEDESCFLAGS.DdSD_HEIGHT;
      backBufferDescription.ddsCaps = CONST_DDSCAPSFLAGS.DdSCAPS_SYSTEMMEMORY;
      // backBufferDescription.ddsCaps = CONST_DDSCAPSFLAGS.DdSCAPS_OFFSCREENPLAIN;
      backBufferDescription.dwWidth = width;
      backBufferDescription.dwHeight = height;
      DirectDrawSurface bBuffer = ddraw.createSurface(ref backBufferDescription);        

      backBuffer = new DirectXOffScreenBuffer(bBuffer, width, height, format, depth);
      // clear backbuffer
      backBuffer.drawFilledRectangle(Color.FromArgb(0,0,0), 0, 0, width,height);
    }
    
    private void createPrimarySurface() {
      STRUCT_DDSURFACEDESC2 primarySurfaceDescription = new STRUCT_DDSURFACEDESC2();
      primarySurfaceDescription.flags = CONST_DDSURFACEDESCFLAGS.DdSD_CAPS;
      primarySurfaceDescription.ddsCaps = CONST_DDSCAPSFLAGS.DdSCAPS_PRIMARYSURFACE;
      primarySurface = ddraw.createSurface(ref primarySurfaceDescription);
    }
    
    /// <see name="DrawSupport.registerView"/> 
    public override void registerView(RFBView view) {
      // creating graphics-Object for view:
      if (views.Count > 0) { throw new Exception("more than one view not possible with direct draw"); }
      if (!views.ContainsKey(view)) {
        
        // initalizing for the view
        ddraw.setCooperativeLevel(view.Handle.ToInt32(), CONST_DDSCLFLAGS.DdSCL_NORMAL);
        
        if (backBuffer == null) { // first view: creating backBuffer
          createBackBuffer();
        }
        if (primarySurface == null) { // first view: creating primary Surface
          createPrimarySurface();
        }
      
        // prepare view
      
        // attaching clipper:
          DirectDrawClipper clipper = ddraw.createClipper(0);
        clipper.setHWnd(view.Handle.ToInt32());
        primarySurface.setClipper(clipper);
        
        views.Add(view,primarySurface);  
      }
    }
    
    /// <see name="DrawSupport.initalize"/> 
    protected override void initalize(PixelFormat format, int width, int height, int depth) {
      this.format = format;
      this.width = width;
      this.height = height;
      this.depth = depth;
    }  

    /// <see name="DrawSupport.drawBackBufferToScreen"/> 
    public override void drawBackBufferToScreen(RFBView screen) {
      drawBackBufferToScreen(screen, new Rectangle(0, 0, width, height));
    }
    
    /// <see name="DrawSupport.drawBackBufferToScreen"/> 
    public override void drawBackBufferToScreen(RFBView screen, Rectangle region) {
      Monitor.Enter(this);

      if (!views.ContainsKey(screen)) { throw new Exception("registerview not called! --> unable to draw"); }
      
      DirectDrawSurface primarySurface = (DirectDrawSurface)views[screen];

      // parameter region defines the changed part of the RFBSurface
      // regionOnScreen specifies the visible Region of the RFBSurface
      
      Rectangle regionOnScreen = screen.ShowedRectangle;
      Rectangle intersection = Rectangle.Intersect(region, regionOnScreen);
      if ((intersection.Width <= 0) || (intersection.Height <= 0)) { Monitor.Exit(this); return; } // nothing visible updated
      // the intersection definies the visible part of the region in RFBSurface-coordinates      
      // identify destination coordinates in screen coordinates 
      
      // the destination
      Rectangle regionDest = new Rectangle();
      Point screenCoord = screen.PointToScreen(new Point(0, 0));
      // intersection.X - regionOnScreen.X lies in the visible area
      regionDest.X = screenCoord.X + (intersection.X - regionOnScreen.X);
      // intersection.Y - regionOnScreen.Y lies in the visible area
      regionDest.Y = screenCoord.Y + (intersection.Y - regionOnScreen.Y);
      regionDest.Width = intersection.Width;
      regionDest.Height = intersection.Height;      
      
      // if surfaces are lost: restore them
      if (primarySurface.isLost()) { primarySurface.restore(); }
      if (backBuffer.getSurface().isLost()) { 
        backBuffer.getSurface().restore();
        // here i need a full update:
        surface.getFullUpdate();
        Monitor.Exit(this);
        return;
      }
      
      // first param: dest, third param source:
      try {
      primarySurface.blt(regionDest, backBuffer.getSurface(), intersection, CONST_DDBLTFLAGS.DdBLT_WAIT);
      } catch (COMException) { } // ignoring Exception due to surface losts ...
      Monitor.Exit(this);
    }

    /// <see name="DrawSupport.getOffScreenBuffer"/>     
    public override OffScreenBuffer getOffScreenBuffer(int width, int height) {
      return new DirectXOffScreenBuffer(width,height,format,ddraw,depth);
    }

    /// <see name="DrawSupport.copyFromBackBuffer"/>         
    public override OffScreenBuffer copyFromBackBuffer(int srcX, int srcY, int width, int height) {
      Monitor.Enter(this);
      OffScreenBuffer dst = getOffScreenBuffer(width,height);
      dst.drawOffScreenBuffer(backBuffer, 0, 0, width, height, srcX, srcY);
      Monitor.Exit(this);
      return dst;
    }
    
    /// <see name="DrawSupport.getDrawingObject"/> 
    public override DrawingObject getDrawingObject(int x, int y, int width, int height) {
      return new DrawingObject(x, y, width, height, backBuffer, this);
    }
    
    /// <see name="DrawSupport.drawingObjectDone"/> 
    protected internal override void drawingObjectDone(int x, int y, int width, int height) {
      // it gets painted to screen, when a screen-update is done with drawBackBufferToScreen ...
    }    
    
    /// <see name="DrawSupport.Dispose"/> 
    public override void Dispose() {
      // waiting for last drawing operation to complete
      Monitor.Enter(this);
      backBuffer.Dispose();
      disposed = true;
      Monitor.Exit(this);
      
    }
  
  }
  
  
  /// <summary>
  /// this class provides an implementation of OffScreenBuffer using DirectX 
  /// </summary>
  public class DirectXOffScreenBuffer : OffScreenBuffer {
    
    private int width;
    private int height;
    private PixelFormat format;
    private DirectDrawSurface buffer;
    private bool disposed = false;
    private int depth;
    private SolidBrush brush;
      
    /// <summary> constructor for DirectXOffScreenBuffer, uses an existing DirectDraw surface to store it's data </summary>
    /// <param name="width">the width of the buffer</param>  
    /// <param name="height">the height of the buffer</param>
    /// <param name="format">the pixelformat for the buffer</param>        
    /// <param name="surface">where the data of the offscreenbuffer is located</param>  
    /// <param name="depth"></param>
    public DirectXOffScreenBuffer(DirectDrawSurface surface, int width, int height, PixelFormat format, int depth) {
      
      // create a buffer from a bufferSurface
      setFields(width,height,format,depth);
      buffer = surface;
      brush = new SolidBrush(new Color());
    }

    /// <summary> constructor for DirectXOffScreenBuffer, creates a DirectDraw surface to store it's data</summary>
    /// <param name="width">the width of the buffer</param>  
    /// <param name="height">the height of the buffer</param>
    /// <param name="format">the pixelformat for the buffer</param>        
    /// <param name="ddraw">the direct-draw instance</param>  
    /// <param name="depth"></param>        
    public DirectXOffScreenBuffer(int width, int height, PixelFormat format, DirectDraw ddraw, int depth) {
      setFields(width,height,format,depth);
      // creating an Systemmem-Surface for the buffer:
      STRUCT_DDSURFACEDESC2 bufferDescription = new STRUCT_DDSURFACEDESC2();
      bufferDescription.flags = CONST_DDSURFACEDESCFLAGS.DdSD_CAPS | CONST_DDSURFACEDESCFLAGS.DdSD_WIDTH | CONST_DDSURFACEDESCFLAGS.DdSD_HEIGHT;
      bufferDescription.ddsCaps = CONST_DDSCAPSFLAGS.DdSCAPS_SYSTEMMEMORY;
      bufferDescription.dwWidth = width;
      bufferDescription.dwHeight = height;
      buffer = ddraw.createSurface(ref bufferDescription);        
    }
    
    private void setFields(int width, int height, PixelFormat format, int depth) {
      this.width = width;
      this.height = height;
      this.format = format;
      this.depth = depth;
    }

    /// <see name="OffScreenBuffer.Width"/> 
    public int Width { get { return width; } }
    /// <see name="OffScreenBuffer.Height"/>     
    public int Height { get  { return height; } }
    
    internal DirectDrawSurface getSurface() { return buffer; }

    /// <see name="OffScreenBuffer.drawFilledRectangle"/>     
    public void drawFilledRectangle(Color color, int x, int y, int width, int height) {
      // efficient DirectDraw variant to draw a rectangle      
      STRUCT_DDBLTFX ddbltfx = new STRUCT_DDBLTFX();
      ddbltfx.dwFillColor = color.ToArgb();
      Rectangle dest = new Rectangle(x,y,width,height);
      buffer.blt(dest, null, dest, CONST_DDBLTFLAGS.DdBLT_COLORFILL, ref ddbltfx);
    }

    /// <see name="OffScreenBuffer.drawOffScreenBuffer"/> 
    public void drawOffScreenBuffer(OffScreenBuffer src, int destX, int destY) {
      drawOffScreenBuffer(src, destX, destY, src.Width, src.Height, 0, 0);
    }
    
    /// <see name="OffScreenBuffer.drawOffScreenBuffer"/> 
    public void drawOffScreenBuffer(OffScreenBuffer src, int destX, int destY, int width, int height, int srcX, int srcY) {
      Rectangle region = new Rectangle();
      region.X = srcX;
      region.Y = srcY;
      region.Width = width;
      region.Height = height;
      
      buffer.bltFast(destX, destY, ((DirectXOffScreenBuffer)src).getSurface(), region, CONST_DDBLTFASTFLAGS.DdBLTFAST_WAIT);
    }
    
    /// <see name="OffScreenBuffer.drawFromByteArray"/> 
    public void drawFromByteArray(byte[] data, int width, int height, int destX, int destY, PixelDecoder usedDecoder) {
      
      GCHandle dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
      IntPtr srcAdr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
      Bitmap bitmap = new Bitmap(width, height, usedDecoder.calculateStride(width), usedDecoder.getTargetPixelFormat(), srcAdr);
      dataHandle.Free();

      Monitor.Enter(this); // DC needs exclusive access to Buffer
      // copying bitmap to surface:
      int bufferDC = buffer.getDC();
      Graphics g = Graphics.FromHdc(new IntPtr(bufferDC));
      g.DrawImage(bitmap, destX, destY);
      g.Dispose();
      buffer.releaseDC(bufferDC);
      Monitor.Exit(this);

      bitmap.Dispose();
    }

    /// <see name="OffScreenBuffer.drawText"/>     
    public void drawText(string text, int x, int y, Font font, Color color) {
      brush.Color = color;
      
      Monitor.Enter(this); // DC needs exclusive access to Buffer
      // copying bitmap to surface:
      int bufferDC = buffer.getDC();
      Graphics g = Graphics.FromHdc(new IntPtr(bufferDC));
      g.DrawString(text, font, brush, x, y);
      
      g.Dispose();
      buffer.releaseDC(bufferDC);
      Monitor.Exit(this);
    }
    
    /// <see name="OffScreenBuffer.Dispose"/> 
    public void Dispose() {
      buffer.Dispose();
      disposed = true;
    }
    
    /// <summary> finalizer </summary>
    ~DirectXOffScreenBuffer() {
      if (!disposed) { Dispose(); }
    }
    
  }
  

  // ***************************************************************************************/  
  // ************************************** Standard GDI+-Implementation *******************/
  // ***************************************************************************************/  
    
  /// <summary>
  /// an implmentation of Drawsupport using the classes provided by the dotNet-Framework
  /// </summary>
  public class DrawDotNetSupport : DrawSupport {
    
    private DotNetOffScreenBuffer buffer;
    private DotNetOffScreenBuffer doubleBuffer;
    private Bitmap backBufferBitmap;
    
    /// <summary> constructor for DrawDotNetSupport </summary>
    /// <param name="format">the pixelformat of the remote framebuffer</param>
    /// <param name="width">the width of the remote framebuffer</param>
    /// <param name="height">the height of the remote framebuffer</param>
    /// <param name="depth"></param>
    public DrawDotNetSupport(PixelFormat format, int width, int height, int depth) {
      initalize(format, width, height, depth);      
    }
    
    /// <see name="DrawSupport.registerView"/> 
    public override void registerView(RFBView view) {
      // creating graphics-Object for view:
      if (!views.ContainsKey(view)) {
        Graphics viewGraphics = view.CreateGraphics();
        views.Add(view, viewGraphics);
      }
    }
    
    /// <see name="DrawSupport.initalize"/>
    protected override void initalize(PixelFormat format, int width, int height, int depth) {
      this.format = format;
      this.width = width;
      this.height = height;
      this.depth = depth;
      
      buffer = (DotNetOffScreenBuffer)getOffScreenBuffer(width,height);
      backBufferBitmap = buffer.getBitmap();
      doubleBuffer = (DotNetOffScreenBuffer)getOffScreenBuffer(width, height);
    }  

    /// <see name="DrawSupport.drawBackBufferToScreen"/>
    public override void drawBackBufferToScreen(RFBView screen) {
      drawBackBufferToScreen(screen, new Rectangle(0, 0, width, height));
    }

    /// <see name="DrawSupport.drawBackBufferToScreen"/>
    public override void drawBackBufferToScreen(RFBView screen, Rectangle region) {
      Monitor.Enter(buffer);
        
      if (!views.ContainsKey(screen)) { throw new Exception("registerview not called! --> unable to draw"); }
      
      // parameter region defines the changed part of the RFBSurface
      // regionOnScreen specifies the visible Region of the RFBSurface
      
      Rectangle regionOnScreen = screen.ShowedRectangle;
      Rectangle intersection = Rectangle.Intersect(region, regionOnScreen);
      if ((intersection.Width <= 0) || (intersection.Height <= 0)) { Monitor.Exit(buffer); return; } // nothing visible updated
      // the intersection definies the visible part of the region in RFBSurface-coordinates      
      // identify destination coordinates in screen coordinates 
      
      // the destination
      Rectangle regionDest = new Rectangle();
      // intersection.X - regionOnScreen.X lies in the visible area
      regionDest.X = (intersection.X - regionOnScreen.X);
      // intersection.Y - regionOnScreen.Y lies in the visible area
      regionDest.Y = (intersection.Y - regionOnScreen.Y);
      regionDest.Width = intersection.Width;
      regionDest.Height = intersection.Height;      
      
      // create Graphics object
      Graphics screenGraphics = screen.CreateGraphics();
      screenGraphics.DrawImage(backBufferBitmap, regionDest, intersection, GraphicsUnit.Pixel);
      screenGraphics.Dispose();

      Monitor.Exit(buffer);
    }

    /// <see name="DrawSupport.getOffScreenBuffer"/>    
    public override OffScreenBuffer getOffScreenBuffer(int width, int height) {
      return new DotNetOffScreenBuffer(width, height, format, depth);
    }
        
    /// <see name="DrawSupport.copyFromBackBuffer"/>
    public override OffScreenBuffer copyFromBackBuffer(int srcX, int srcY, int width, int height) {
      Monitor.Enter(buffer);
      OffScreenBuffer dst = getOffScreenBuffer(width,height);
      dst.drawOffScreenBuffer(buffer, 0, 0, width, height, srcX, srcY);
      Monitor.Exit(buffer);
      return dst;
    }
    
    /// <see name="DrawSupport.getDrawingObject"/>    
    public override DrawingObject getDrawingObject(int x, int y, int width, int height) {
      return new DrawingObject(x, y, width, height, doubleBuffer, this);
    }
    
    /// <see name="DrawSupport.drawingObjectDone"/>
    protected internal override void drawingObjectDone(int x, int y, int width, int height) {
      Monitor.Enter(buffer);
      buffer.drawOffScreenBuffer(doubleBuffer, x, y, width, height, x, y);
      Monitor.Exit(buffer);
    }    
    
    /// <see name="DrawSupport.Dispose"/>
    public override void Dispose() {
      // waiting for last drawing operation to complete
      Monitor.Enter(buffer);
      buffer.Dispose();
      doubleBuffer.Dispose();
      disposed = true;
      Monitor.Exit(buffer);
    }  
    
  }
  
  
  /// <summary>
  /// An implementation of OffScreenBuffer using the classes provided by the dotNet Framework
  /// </summary>
  public class DotNetOffScreenBuffer : OffScreenBuffer {
    
    private int width;
    private int height;
    private PixelFormat format;
    private Bitmap buffer;
    private SolidBrush brush;
    private Graphics graphics;
    private bool disposed = false;
    private int depth;
    
    /// <summary> constructor for DotNetOffScreenBuffer, uses an existing Bitmap to store it's data </summary>
    /// <param name="bitmap">where the data of the offscreenbuffer is located</param>  
    /// <param name="depth"></param>
    public DotNetOffScreenBuffer(Bitmap bitmap, int depth) {
      buffer = bitmap;
      width = bitmap.Width;
      height = bitmap.Height;
      format = bitmap.PixelFormat;
      this.depth = depth;
      brush = new SolidBrush(new Color());
      graphics = Graphics.FromImage(bitmap);
    }
    
    /// <summary> constructor for DotNetOffScreenBuffer, creates a new Bitmap to store it's data </summary>
    /// <param name="width">the width of the buffer</param>  
    /// <param name="height">the height of the buffer</param>
    /// <param name="format">the pixelformat for the buffer</param>
    /// <param name="depth"></param>
    public DotNetOffScreenBuffer(int width, int height, PixelFormat format, int depth) {
      this.width = width;
      this.height = height;
      this.format = format;
      this.depth = depth;
      buffer = new Bitmap(width, height, format);
      graphics = Graphics.FromImage(buffer);
      brush = new SolidBrush(new Color());
    }
    
    /// <see name="OffScreenBuffer.Width"/> 
    public int Width { get { return width; } }
    /// <see name="OffScreenBuffer.Height"/> 
    public int Height { get  { return height; } }
    
    internal Bitmap getBitmap() { return buffer; }
    
    /// <see name="OffScreenBuffer.drawFilledRectangle"/> 
    public void drawFilledRectangle(Color color, int x, int y, int width, int height) {
      brush.Color = color;
      graphics.FillRectangle(brush, x, y, width, height);  
    }
    
    /// <see name="OffScreenBuffer.drawOffScreenBuffer"/>     
    public void drawOffScreenBuffer(OffScreenBuffer src, int destX, int destY) {
      graphics.DrawImage(((DotNetOffScreenBuffer)src).getBitmap(), destX, destY);
    }

    /// <see name="OffScreenBuffer.drawOffScreenBuffer"/>     
    public void drawOffScreenBuffer(OffScreenBuffer src, int destX, int destY, int width, int height, int srcX, int srcY) {
      graphics.DrawImage(((DotNetOffScreenBuffer)src).getBitmap(), destX, destY, new Rectangle(srcX, srcY, width, height), GraphicsUnit.Pixel);
    }
    
    /// <see name="OffScreenBuffer.drawFromByteArray"/>     
    public void drawFromByteArray(byte[] data, int width, int height, int destX, int destY, PixelDecoder usedDecoder) {
      // decoding:
      GCHandle dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
      IntPtr srcAdr = Marshal.UnsafeAddrOfPinnedArrayElement(data, 0);
      Bitmap bitmap = new Bitmap(width, height, usedDecoder.calculateStride(width), usedDecoder.getTargetPixelFormat(), srcAdr);
      dataHandle.Free();

      // drawing
      graphics.DrawImage(bitmap, destX, destY);  
      bitmap.Dispose();
    }
    
    /// <see name="OffScreenBuffer.drawText"/> 
    public void drawText(string text, int x, int y, Font font, Color color) {
      brush.Color = color;
      graphics.DrawString(text, font, brush, x, y);
    }

    /// <see name="OffScreenBuffer.Dispose"/>     
    public void Dispose() {
      brush.Dispose();
      graphics.Dispose();
      buffer.Dispose();
      disposed = true;
    }
    /// <summary> finalizer </summary>
    ~DotNetOffScreenBuffer() {
      if (!disposed) { Dispose(); }
    }
      
  }  


} 
www.java2v.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.