Created branch for Mac OS support.

This commit is contained in:
kanato 2008-11-04 16:50:31 +00:00
commit 7b1c546abd
51 changed files with 1746 additions and 442 deletions

View file

@ -1,8 +1,19 @@
[Legend: complete('+') | WIP('*') | missing('-')] [Legend: complete('+') | WIP('*') | missing('-')]
----------------------- ---------------------
OpenTK 0.9.1 -> 0.9.2
---------------------
+ OpenTK
+ Platform
+ Added GdiPlus bindings.
+ Utilities
+ Fonts
+ Updated the layout code to use the new GdiPlus bindings.
---------------------
OpenTK 0.9.0 -> 0.9.1 OpenTK 0.9.0 -> 0.9.1
----------------------- ---------------------
+ Bind + Bind
+ Corrected Glu.NewTess and Glu.DeleteTess (were NewTes and DeleteTes respectively). + Corrected Glu.NewTess and Glu.DeleteTess (were NewTes and DeleteTes respectively).
+ Corrected typemaping for NurbsObj, QuadricObj, TesselatorObj and FunctionPointer. + Corrected typemaping for NurbsObj, QuadricObj, TesselatorObj and FunctionPointer.

View file

@ -173,10 +173,15 @@ Extensions define:
############################################################################### ###############################################################################
# #
# Edited by Stefanos Apostolopoulos for OpenTK. Revision 2 # Edited by Stefanos Apostolopoulos for OpenTK. Revision 3
# #
############################################################################### ###############################################################################
StencilFace enum:
use DrawBufferMode FRONT
use DrawBufferMode BACK
use DrawBufferMode FRONT_AND_BACK
DrawElementsType enum: DrawElementsType enum:
use DataType UNSIGNED_BYTE use DataType UNSIGNED_BYTE
use DataType UNSIGNED_SHORT use DataType UNSIGNED_SHORT
@ -285,15 +290,18 @@ AlphaFunction enum:
############################################################################### ###############################################################################
# Edited for OpenTK
BlendingFactorDest enum: BlendingFactorDest enum:
ZERO = 0 ZERO = 0
ONE = 1 ONE = 1
SRC_COLOR = 0x0300 SRC_COLOR = 0x0300
ONE_MINUS_SRC_COLOR = 0x0301 ONE_MINUS_SRC_COLOR = 0x0301
DST_COLOR = 0x0306
ONE_MINUS_DST_COLOR = 0x0307
SRC_ALPHA = 0x0302 SRC_ALPHA = 0x0302
ONE_MINUS_SRC_ALPHA = 0x0303 ONE_MINUS_SRC_ALPHA = 0x0303
DST_ALPHA = 0x0304 DST_ALPHA = 0x0304
ONE_MINUS_DST_ALPHA = 0x0305 ONE_MINUS_DST_ALPHA = 0x0305
use EXT_blend_color CONSTANT_COLOR_EXT use EXT_blend_color CONSTANT_COLOR_EXT
use EXT_blend_color ONE_MINUS_CONSTANT_COLOR_EXT use EXT_blend_color ONE_MINUS_CONSTANT_COLOR_EXT
use EXT_blend_color CONSTANT_ALPHA_EXT use EXT_blend_color CONSTANT_ALPHA_EXT
@ -301,16 +309,19 @@ BlendingFactorDest enum:
############################################################################### ###############################################################################
# Edited for OpenTK
BlendingFactorSrc enum: BlendingFactorSrc enum:
use BlendingFactorDest ZERO use BlendingFactorDest ZERO
use BlendingFactorDest ONE use BlendingFactorDest ONE
DST_COLOR = 0x0306 use BlendingFactorDest SRC_COLOR
ONE_MINUS_DST_COLOR = 0x0307 use BlendingFactorDest ONE_MINUS_SRC_COLOR
SRC_ALPHA_SATURATE = 0x0308 use BlendingFactorDest DST_COLOR
use BlendingFactorDest ONE_MINUS_DST_COLOR
use BlendingFactorDest SRC_ALPHA use BlendingFactorDest SRC_ALPHA
use BlendingFactorDest ONE_MINUS_SRC_ALPHA use BlendingFactorDest ONE_MINUS_SRC_ALPHA
use BlendingFactorDest DST_ALPHA use BlendingFactorDest DST_ALPHA
use BlendingFactorDest ONE_MINUS_DST_ALPHA use BlendingFactorDest ONE_MINUS_DST_ALPHA
SRC_ALPHA_SATURATE = 0x0308
use EXT_blend_color CONSTANT_COLOR_EXT use EXT_blend_color CONSTANT_COLOR_EXT
use EXT_blend_color ONE_MINUS_CONSTANT_COLOR_EXT use EXT_blend_color ONE_MINUS_CONSTANT_COLOR_EXT
use EXT_blend_color CONSTANT_ALPHA_EXT use EXT_blend_color CONSTANT_ALPHA_EXT

View file

@ -5868,12 +5868,14 @@ StencilOpSeparate(face, sfail, dpfail, dppass)
glsopcode ? glsopcode ?
offset ? offset ?
StencilFuncSeparate(frontfunc, backfunc, ref, mask)
# Edited for OpenTK
StencilFuncSeparate(face, func, ref, mask)
return void return void
param frontfunc StencilFunction in value param face StencilFace in value
param backfunc StencilFunction in value param func StencilFunction in value
param ref ClampedStencilValue in value param ref ClampedStencilValue in value
param mask MaskedStencilValue in value param mask MaskedStencilValue in value
category VERSION_2_0 category VERSION_2_0
version 2.0 version 2.0
extension extension

View file

@ -25,7 +25,7 @@ namespace Examples.OpenAL
const int buffer_size = (int)(0.5*44100); const int buffer_size = (int)(0.5*44100);
const int buffer_count = 4; const int buffer_count = 4;
static object openal_lock = new object(); // Should be global in your app. //static object openal_lock = new object(); // Should be global in your app.
public static void Main() public static void Main()
{ {

View file

@ -165,6 +165,28 @@ namespace Examples.Tutorial
bitmap.UnlockBits(data); bitmap.UnlockBits(data);
} }
#endregion Textures #endregion Textures
Keyboard.KeyUp += KeyUp;
}
int i = 0;
void KeyUp(OpenTK.Input.KeyboardDevice sender, OpenTK.Input.Key e)
{
if (e == OpenTK.Input.Key.F12)
{
Bitmap bmp = new Bitmap(this.Width, this.Height);
System.Drawing.Imaging.BitmapData data =
bmp.LockBits(new Rectangle(0, 0, this.Width, this.Height),
System.Drawing.Imaging.ImageLockMode.WriteOnly,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
GL.ReadPixels(0, 0, this.Width, this.Height,
OpenTK.Graphics.PixelFormat.Bgr,
OpenTK.Graphics.PixelType.UnsignedByte,
data.Scan0);
bmp.UnlockBits(data);
bmp.RotateFlip(RotateFlipType.RotateNoneFlipY);
bmp.Save("Screenshot" + (i++).ToString() + ".png", ImageFormat.Png);
}
} }
#endregion #endregion

View file

@ -0,0 +1,69 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK team.
* This notice may not be removed.
* See license.txt for licensing detailed licensing details.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
#if false
using System.Xml.Serialization;
using OpenTK.Math;
namespace Examples.Tests
{
[Example("Serialization", ExampleCategory.Test)]
public class MathSerialization
{
public static void Main()
{
using (MemoryStream stream = new MemoryStream())
{
XmlSerializer xs = new XmlSerializer(typeof(Matrix4));
{
XmlWriterSettings settings = new XmlWriterSettings();
settings.NewLineHandling = NewLineHandling.Entitize;
settings.Indent = true;
XmlWriter xw = XmlTextWriter.Create(stream, settings);
xs.Serialize(xw, Matrix4.Identity);
xw.Close();
}
stream.Position = 0;
byte[] text = new byte[stream.Length];
int pos = 0;
do
{
pos += stream.Read(text, pos, (int)stream.Length);
}
while (pos != stream.Length);
Console.WriteLine(System.Text.Encoding.Default.GetChars(text));
stream.Position = 0;
Matrix4 matrix = (Matrix4)xs.Deserialize(stream);
if (Matrix4.Identity == matrix)
Console.WriteLine("Matrix deserialized correctly.");
else
Console.WriteLine("Error deserializing matrix.");
Console.WriteLine("Press any key to continue...");
Console.ReadKey(false);
}
}
}
}
#endif

View file

@ -17,6 +17,7 @@ namespace Examples.Tests
{ {
public static void Main() public static void Main()
{ {
/*
Stopwatch watch = new Stopwatch(); Stopwatch watch = new Stopwatch();
Vector3 a = new Vector3(0.0f, 0.0f, 0.0f); Vector3 a = new Vector3(0.0f, 0.0f, 0.0f);
@ -31,7 +32,7 @@ namespace Examples.Tests
Vector3.Add(ref a, ref b, out res); Vector3.Add(ref a, ref b, out res);
res = a + b; res = a + b;
res = Vector3.Zero; res = Vector3.Zero;
/*
watch.Reset(); watch.Reset();
watch.Start(); watch.Start();
for (int i = 100000000; --i != 0; ) for (int i = 100000000; --i != 0; )
@ -82,12 +83,12 @@ namespace Examples.Tests
*/ */
} }
static Vector3 pos = new Vector3(); //static Vector3 pos = new Vector3();
static Vector3 Pos //static Vector3 Pos
{ //{
get { return pos; } // get { return pos; }
set { pos = value; } // set { pos = value; }
} //}
} }
} }

View file

@ -175,10 +175,11 @@ namespace Examples.Tutorial
} }
// Move to the right, and print using the second font. // Move to the right, and print using the second font.
float width, height; //float width, height;
fonts[handles.Length / 2 - 1].MeasureString(text, out width, out height); //fonts[handles.Length / 2 - 1].MeasureString(text, out width, out height);
RectangleF rect = fonts[handles.Length / 2 - 1].MeasureText(text);
GL.LoadIdentity(); GL.LoadIdentity();
GL.Translate(width + 32.0f, 0, 0); GL.Translate(rect.Width + 32.0f, 0, 0);
for (int i = handles.Length / 2; i < handles.Length; i++) for (int i = handles.Length / 2; i < handles.Length; i++)
{ {
printer.Draw(handles[i]); printer.Draw(handles[i]);

View file

@ -30,8 +30,8 @@ namespace Examples.Tutorial
float angle = 0.0f; float angle = 0.0f;
Shapes.Shape shape = new Examples.Shapes.Plane(16, 16, 2.0f, 2.0f); Shapes.Shape shape = new Examples.Shapes.Plane(16, 16, 2.0f, 2.0f);
TextureFont sans = new TextureFont(new Font(FontFamily.GenericSansSerif, 32, FontStyle.Regular, //TextureFont sans = new TextureFont(new Font(FontFamily.GenericSansSerif, 32, FontStyle.Regular,
GraphicsUnit.Pixel)); // GraphicsUnit.Pixel));
#region Constructor #region Constructor

View file

@ -27,7 +27,7 @@ namespace Examples.Tutorial
#region --- Private Fields --- #region --- Private Fields ---
Shapes.Shape cube = new Examples.Shapes.Cube(); Shapes.Shape cube = new Examples.Shapes.Cube();
Shapes.Shape plane = new Examples.Shapes.Plane(16, 16, 2.0f, 2.0f); //Shapes.Shape plane = new Examples.Shapes.Plane(16, 16, 2.0f, 2.0f);
struct Vbo struct Vbo
{ {

View file

@ -125,7 +125,7 @@ namespace Examples.Tutorial
// used in 2d graphics, and is necessary for achieving pixel-perfect glyph rendering. // used in 2d graphics, and is necessary for achieving pixel-perfect glyph rendering.
// TextPrinter.End() restores your previous projection/modelview matrices. // TextPrinter.End() restores your previous projection/modelview matrices.
text.Begin(); text.Begin();
GL.Color3(Color.PaleGoldenrod); GL.Color3(Color.LightBlue);
text.Draw((1.0 / e.Time).ToString("F2"), sans); text.Draw((1.0 / e.Time).ToString("F2"), sans);
GL.Translate(0.0f, current_position, 0.0f); GL.Translate(0.0f, current_position, 0.0f);
GL.Color3(Color.White); GL.Color3(Color.White);

View file

@ -15,6 +15,11 @@ namespace Examples.WinForms
{ {
Color clearColor; Color clearColor;
public DerivedGLControl()
{
this.InitializeComponent();
}
public Color ClearColor public Color ClearColor
{ {
get { return clearColor; } get { return clearColor; }

View file

@ -27,7 +27,7 @@ namespace Examples.WinForms
GLControl glControl = new GLControl(GraphicsMode.Default); GLControl glControl = new GLControl(GraphicsMode.Default);
Type glClass; Type glClass;
Type delegatesClass; Type delegatesClass;
Type importsClass; //Type importsClass;
int supported, all; // Number of supported extensions. int supported, all; // Number of supported extensions.
string driver; string driver;
@ -37,7 +37,7 @@ namespace Examples.WinForms
glClass = typeof(GL); glClass = typeof(GL);
delegatesClass = glClass.GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic); delegatesClass = glClass.GetNestedType("Delegates", BindingFlags.Static | BindingFlags.NonPublic);
importsClass = glClass.GetNestedType("Imports", BindingFlags.Static | BindingFlags.NonPublic); //importsClass = glClass.GetNestedType("Imports", BindingFlags.Static | BindingFlags.NonPublic);
glControl.CreateControl(); glControl.CreateControl();
Application.Idle += StartAsync; Application.Idle += StartAsync;

View file

@ -256,12 +256,12 @@ namespace OpenTK.Audio
if (!String.IsNullOrEmpty(device)) if (!String.IsNullOrEmpty(device))
device_handle = Alc.OpenDevice(device); device_handle = Alc.OpenDevice(device);
if (device_handle == IntPtr.Zero)
device_handle = Alc.OpenDevice(null);
if (device_handle == IntPtr.Zero) if (device_handle == IntPtr.Zero)
Alc.OpenDevice(Alc.GetString(IntPtr.Zero, AlcGetString.DefaultDeviceSpecifier)); Alc.OpenDevice(Alc.GetString(IntPtr.Zero, AlcGetString.DefaultDeviceSpecifier));
if (device_handle == IntPtr.Zero && available_devices.Count > 0) if (device_handle == IntPtr.Zero && available_devices.Count > 0)
device_handle = Alc.OpenDevice(available_devices[0]); device_handle = Alc.OpenDevice(available_devices[0]);
if (device_handle == IntPtr.Zero)
device_handle = Alc.OpenDevice(null);
if (device_handle == IntPtr.Zero) if (device_handle == IntPtr.Zero)
throw new AudioDeviceException(String.Format("Audio device '{0}' does not exist or is tied up by another application.", throw new AudioDeviceException(String.Format("Audio device '{0}' does not exist or is tied up by another application.",
String.IsNullOrEmpty(device) ? "default" : device)); String.IsNullOrEmpty(device) ? "default" : device));

View file

@ -16,7 +16,7 @@ using OpenTK.Math;
/* Type Mapping /* Type Mapping
// 8-bit boolean // 8-bit boolean
typedef char ALboolean; typedef char ALboolean;
* byte * bool
// character // character
typedef char ALchar; typedef char ALchar;
* byte * byte
@ -26,7 +26,7 @@ typedef char ALbyte;
// unsigned 8-bit integer // unsigned 8-bit integer
typedef unsigned char ALubyte; typedef unsigned char ALubyte;
* ubyte * byte
// signed 16-bit 2's complement integer // signed 16-bit 2's complement integer
typedef short ALshort; typedef short ALshort;
@ -67,6 +67,7 @@ namespace OpenTK.Audio
{ {
public static partial class AL public static partial class AL
{ {
#region Constants #region Constants
public const string Lib = "openal32.dll"; public const string Lib = "openal32.dll";
@ -441,6 +442,14 @@ namespace OpenTK.Audio
return (int)temp; return (int)temp;
} }
/// <summary>This function generates one source only. References to sources are uint values, which are used wherever a source reference is needed (in calls such as AL.DeleteSources and AL.Source with parameter ALSourcei).</summary>
/// <param name="source">Pointer to an uint value which will store the name of the new source.</param>
[CLSCompliant( false )]
public static void GenSource( out uint source )
{
GenSources( 1, out source );
}
#endregion GenSources() #endregion GenSources()
#region DeleteSources() #region DeleteSources()
@ -490,7 +499,7 @@ namespace OpenTK.Audio
/// <summary>This function deletes one source only.</summary> /// <summary>This function deletes one source only.</summary>
/// <param name="source">Pointer to a source name identifying the source to be deleted.</param> /// <param name="source">Pointer to a source name identifying the source to be deleted.</param>
[CLSCompliant(false)] [CLSCompliant(false)]
public static void DeleteSource(uint source) public static void DeleteSource( ref uint source)
{ {
DeleteSources(1, ref source); DeleteSources(1, ref source);
} }
@ -1305,6 +1314,14 @@ namespace OpenTK.Audio
return (int)temp; return (int)temp;
} }
/// <summary>This function generates one buffer only, which contain audio data (see AL.BufferData). References to buffers are uint values, which are used wherever a buffer reference is needed (in calls such as AL.DeleteBuffers, AL.Source with parameter ALSourcei, AL.SourceQueueBuffers, and AL.SourceUnqueueBuffers).</summary>
/// <param name="buffers">Pointer to an uint value which will store the names of the new buffer.</param>
[CLSCompliant( false )]
public static void GenBuffer( out uint buffer )
{
GenBuffers( 1, out buffer );
}
#endregion GenBuffers #endregion GenBuffers
#region DeleteBuffers #region DeleteBuffers
@ -1355,7 +1372,7 @@ namespace OpenTK.Audio
/// <summary>This function deletes one buffer only, freeing the resources used by the buffer. Buffers which are attached to a source can not be deleted. See AL.Source (ALSourcei) and AL.SourceUnqueueBuffers for information on how to detach a buffer from a source.</summary> /// <summary>This function deletes one buffer only, freeing the resources used by the buffer. Buffers which are attached to a source can not be deleted. See AL.Source (ALSourcei) and AL.SourceUnqueueBuffers for information on how to detach a buffer from a source.</summary>
/// <param name="buffer">Pointer to a buffer name identifying the buffer to be deleted.</param> /// <param name="buffer">Pointer to a buffer name identifying the buffer to be deleted.</param>
[CLSCompliant(false)] [CLSCompliant(false)]
public static void DeleteBuffer(uint buffer) public static void DeleteBuffer( ref uint buffer)
{ {
DeleteBuffers(1, ref buffer); DeleteBuffers(1, ref buffer);
} }
@ -1363,7 +1380,7 @@ namespace OpenTK.Audio
/// <summary>This function deletes one buffer only, freeing the resources used by the buffer. Buffers which are attached to a source can not be deleted. See AL.Source (ALSourcei) and AL.SourceUnqueueBuffers for information on how to detach a buffer from a source.</summary> /// <summary>This function deletes one buffer only, freeing the resources used by the buffer. Buffers which are attached to a source can not be deleted. See AL.Source (ALSourcei) and AL.SourceUnqueueBuffers for information on how to detach a buffer from a source.</summary>
/// <param name="buffer">Pointer to a buffer name identifying the buffer to be deleted.</param> /// <param name="buffer">Pointer to a buffer name identifying the buffer to be deleted.</param>
[CLSCompliant(true)] [CLSCompliant(true)]
public static void DeleteBuffer(int buffer) public static void DeleteBuffer( int buffer)
{ {
DeleteBuffers(1, ref buffer); DeleteBuffers(1, ref buffer);
} }
@ -1560,5 +1577,59 @@ namespace OpenTK.Audio
// AL_API void AL_APIENTRY alDistanceModel( ALenum distanceModel ); // AL_API void AL_APIENTRY alDistanceModel( ALenum distanceModel );
#endregion Global Parameters #endregion Global Parameters
#region Helpers
/// <summary>(Helper) Returns Source state information.</summary>
/// <param name="sid">The source to be queried.</param>
/// <returns>state information from OpenAL.</returns>
[CLSCompliant( false )]
public static ALSourceState GetSourceState( uint sid )
{
int temp;
AL.GetSource( sid, ALGetSourcei.SourceState, out temp );
return (ALSourceState) temp;
}
/// <summary>(Helper) Returns Source state information.</summary>
/// <param name="sid">The source to be queried.</param>
/// <returns>state information from OpenAL.</returns>
[CLSCompliant( true )]
public static ALSourceState GetSourceState( int sid )
{
int temp;
AL.GetSource( sid, ALGetSourcei.SourceState, out temp );
return (ALSourceState) temp;
}
/// <summary>(Helper) Returns Source type information.</summary>
/// <param name="sid">The source to be queried.</param>
/// <returns>type information from OpenAL.</returns>
[CLSCompliant( false )]
public static ALSourceType GetSourceType( uint sid )
{
int temp;
AL.GetSource( sid, ALGetSourcei.SourceType, out temp );
return (ALSourceType) temp;
}
/// <summary>(Helper) Returns Source type information.</summary>
/// <param name="sid">The source to be queried.</param>
/// <returns>type information from OpenAL.</returns>
[CLSCompliant( true )]
public static ALSourceType GetSourceType( int sid )
{
int temp;
AL.GetSource( sid, ALGetSourcei.SourceType, out temp );
return (ALSourceType) temp;
}
[CLSCompliant( true )]
public static ALDistanceModel GetDistanceModel( )
{
return (ALDistanceModel) AL.Get( ALGetInteger.DistanceModel );
}
#endregion Helpers
} }
} }

View file

@ -17,6 +17,7 @@ namespace OpenTK.Audio
{ {
public partial class EffectsExtension public partial class EffectsExtension
{ {
#region Helpers #region Helpers
#region BindEffect #region BindEffect
@ -184,6 +185,22 @@ namespace OpenTK.Audio
return temp; return temp;
} }
/// <summary>Generates a single effect object.</summary>
/// <param name="effect">A handle to the generated effect object.</param>
[CLSCompliant(false)]
public void GenEffect( out uint effect )
{
unsafe
{
fixed ( uint* ptr = &effect )
{
Imported_alGenEffects( 1, ptr );
effect = *ptr;
}
}
}
#endregion alGenEffects #endregion alGenEffects
#region alDeleteEffects #region alDeleteEffects
@ -244,10 +261,21 @@ namespace OpenTK.Audio
/// <summary>This function deletes one Effect only.</summary> /// <summary>This function deletes one Effect only.</summary>
/// <param name="effect">Pointer to an effect name/handle identifying the Effect Object to be deleted.</param> /// <param name="effect">Pointer to an effect name/handle identifying the Effect Object to be deleted.</param>
public void DeleteEffect(int effect) public void DeleteEffect(int effect)
{
DeleteEffects( 1, ref effect );
}
/// <summary>This function deletes one Effect only.</summary>
/// <param name="effect">Pointer to an effect name/handle identifying the Effect Object to be deleted.</param>
[CLSCompliant(false)]
public void DeleteEffect( ref uint effect )
{ {
unsafe unsafe
{ {
Imported_alDeleteEffects(1, (uint*)&effect); fixed ( uint* ptr = &effect )
{
Imported_alDeleteEffects( 1, ptr );
}
} }
} }
@ -560,7 +588,7 @@ namespace OpenTK.Audio
} }
/// <summary>This function generates only one Filter.</summary> /// <summary>This function generates only one Filter.</summary>
/// <returns>Storage UInt32 for the new filter name/handle.</returns> /// <returns>Storage Int32 for the new filter name/handle.</returns>
public int GenFilter() public int GenFilter()
{ {
int filter; int filter;
@ -568,6 +596,21 @@ namespace OpenTK.Audio
return filter; return filter;
} }
/// <summary>This function generates only one Filter.</summary>
/// <param name="filter">Storage UInt32 for the new filter name/handle.</param>
[CLSCompliant(false)]
unsafe public void GenFilter( out uint filter )
{
unsafe
{
fixed ( uint* ptr = &filter )
{
Imported_alGenFilters( 1, ptr );
filter = *ptr;
}
}
}
#endregion alGenFilters #endregion alGenFilters
#region alDeleteFilters #region alDeleteFilters
@ -632,6 +675,20 @@ namespace OpenTK.Audio
DeleteFilters(1, ref filter); DeleteFilters(1, ref filter);
} }
/// <summary>This function deletes one Filter only.</summary>
/// <param name="filter">Pointer to an filter name/handle identifying the Filter Object to be deleted.</param>
[CLSCompliant(false)]
public void DeleteFilter( ref uint filter )
{
unsafe
{
fixed ( uint* ptr = &filter )
{
Imported_alDeleteFilters( 1, ptr );
}
}
}
#endregion alDeleteFilters #endregion alDeleteFilters
#region alIsFilter #region alIsFilter
@ -864,14 +921,29 @@ namespace OpenTK.Audio
} }
/// <summary>This function generates only one Auxiliary Effect Slot.</summary> /// <summary>This function generates only one Auxiliary Effect Slot.</summary>
/// <returns>Storage UInt32 for the new auxiliary effect slot name/handle.</returns> /// <returns>Storage Int32 for the new auxiliary effect slot name/handle.</returns>
public int GenAuxiliaryEffectSlots() public int GenAuxiliaryEffectSlot()
{ {
int temp; int temp;
GenAuxiliaryEffectSlots(1, out temp); GenAuxiliaryEffectSlots(1, out temp);
return temp; return temp;
} }
/// <summary>This function generates only one Auxiliary Effect Slot.</summary>
/// <returns>Storage UInt32 for the new auxiliary effect slot name/handle.</returns>
[CLSCompliant(false)]
public void GenAuxiliaryEffectSlot( out uint slot )
{
unsafe
{
fixed ( uint* ptr = &slot )
{
Imported_alGenAuxiliaryEffectSlots( 1, ptr );
slot = *ptr;
}
}
}
#endregion alGenAuxiliaryEffectSlots #endregion alGenAuxiliaryEffectSlots
#region DeleteAuxiliaryEffectSlots #region DeleteAuxiliaryEffectSlots
@ -930,7 +1002,7 @@ namespace OpenTK.Audio
/// <summary>This function deletes one AuxiliaryEffectSlot only.</summary> /// <summary>This function deletes one AuxiliaryEffectSlot only.</summary>
/// <param name="slot">Pointer to an auxiliary effect slot name/handle identifying the Auxiliary Effect Slot Object to be deleted.</param> /// <param name="slot">Pointer to an auxiliary effect slot name/handle identifying the Auxiliary Effect Slot Object to be deleted.</param>
public void DeleteAuxiliaryEffectSlots(int slot) public void DeleteAuxiliaryEffectSlot(int slot)
{ {
DeleteAuxiliaryEffectSlots(1, ref slot); DeleteAuxiliaryEffectSlots(1, ref slot);
} }
@ -938,9 +1010,15 @@ namespace OpenTK.Audio
/// <summary>This function deletes one AuxiliaryEffectSlot only.</summary> /// <summary>This function deletes one AuxiliaryEffectSlot only.</summary>
/// <param name="slot">Pointer to an auxiliary effect slot name/handle identifying the Auxiliary Effect Slot Object to be deleted.</param> /// <param name="slot">Pointer to an auxiliary effect slot name/handle identifying the Auxiliary Effect Slot Object to be deleted.</param>
[CLSCompliant(false)] [CLSCompliant(false)]
public void DeleteAuxiliaryEffectSlots(uint slot) public void DeleteAuxiliaryEffectSlot( ref uint slot)
{ {
DeleteAuxiliaryEffectSlots(1, ref slot); unsafe
{
fixed ( uint* ptr = &slot )
{
Imported_alDeleteAuxiliaryEffectSlots( 1, ptr );
}
}
} }
#endregion alDeleteAuxiliaryEffectSlots #endregion alDeleteAuxiliaryEffectSlots

View file

@ -12,7 +12,7 @@ using System.Text;
namespace OpenTK.Audio namespace OpenTK.Audio
{ {
/// <summary>Encapsulates a pointer to decoded sound buffer.</summary> /// <summary>Encapsulates a pointer to a decoded sound buffer.</summary>
public class SoundData public class SoundData
{ {
byte[] buffer; byte[] buffer;

View file

@ -436,7 +436,7 @@ namespace OpenTK
#endif #endif
#region void Run() #region public void Run()
/// <summary> /// <summary>
/// Enters the game loop of the GameWindow updating and rendering at the maximum possible frequency. /// Enters the game loop of the GameWindow updating and rendering at the maximum possible frequency.
@ -448,6 +448,10 @@ namespace OpenTK
Run(0.0, 0.0); Run(0.0, 0.0);
} }
#endregion
#region public void Run(double updateFrequency)
/// <summary> /// <summary>
/// Enters the game loop of the GameWindow updating the specified update frequency, while maintaining the /// Enters the game loop of the GameWindow updating the specified update frequency, while maintaining the
/// maximum possible render frequency. /// maximum possible render frequency.
@ -459,6 +463,10 @@ namespace OpenTK
Run(updateFrequency, 0.0); Run(updateFrequency, 0.0);
} }
#endregion
#region public void Run(double updates_per_second, double frames_per_second)
/// <summary> /// <summary>
/// Enters the game loop of the GameWindow updating and rendering at the specified frequency. /// Enters the game loop of the GameWindow updating and rendering at the specified frequency.
/// </summary> /// </summary>
@ -1364,14 +1372,20 @@ namespace OpenTK
/// <summary> /// <summary>
/// Disposes of the GameWindow, releasing all resources consumed by it. /// Disposes of the GameWindow, releasing all resources consumed by it.
/// </summary> /// </summary>
public virtual void Dispose() public void Dispose()
{ {
if (disposed) throw new ObjectDisposedException("GameWindow"); try
Dispose(true); {
Dispose(true);
}
finally
{
DisposeInternal(true);
}
GC.SuppressFinalize(this); GC.SuppressFinalize(this);
} }
private void Dispose(bool manual) private void DisposeInternal(bool manual)
{ {
if (!disposed) if (!disposed)
{ {
@ -1393,10 +1407,19 @@ namespace OpenTK
} }
} }
/// <summary>Finalizes unmanaged resources consumed by the GameWindow.</summary> /// <summary>
/// Override to add custom cleanup logic.
/// </summary>
/// <param name="manual">True, if this method was called by the application; false if this was called by the finalizer thread.</param>
protected virtual void Dispose(bool manual)
{
}
///// <summary>Finalizes unmanaged resources consumed by the GameWindow.</summary>
//~GameWindow() //~GameWindow()
//{ //{
// Dispose(false); // Dispose(false);
// DisposeInternal(false);
//} //}
#endregion #endregion

View file

@ -9532,15 +9532,15 @@ namespace OpenTK.Graphics
[System.CLSCompliant(false)] [System.CLSCompliant(false)]
public static public static
void StencilFuncSeparate(OpenTK.Graphics.StencilFunction frontfunc, OpenTK.Graphics.StencilFunction backfunc, Int32 @ref, UInt32 mask) void StencilFuncSeparate(OpenTK.Graphics.StencilFace face, OpenTK.Graphics.StencilFunction func, Int32 @ref, UInt32 mask)
{ {
Delegates.glStencilFuncSeparate((OpenTK.Graphics.StencilFunction)frontfunc, (OpenTK.Graphics.StencilFunction)backfunc, (Int32)@ref, (UInt32)mask); Delegates.glStencilFuncSeparate((OpenTK.Graphics.StencilFace)face, (OpenTK.Graphics.StencilFunction)func, (Int32)@ref, (UInt32)mask);
} }
public static public static
void StencilFuncSeparate(OpenTK.Graphics.StencilFunction frontfunc, OpenTK.Graphics.StencilFunction backfunc, Int32 @ref, Int32 mask) void StencilFuncSeparate(OpenTK.Graphics.StencilFace face, OpenTK.Graphics.StencilFunction func, Int32 @ref, Int32 mask)
{ {
Delegates.glStencilFuncSeparate((OpenTK.Graphics.StencilFunction)frontfunc, (OpenTK.Graphics.StencilFunction)backfunc, (Int32)@ref, (UInt32)mask); Delegates.glStencilFuncSeparate((OpenTK.Graphics.StencilFace)face, (OpenTK.Graphics.StencilFunction)func, (Int32)@ref, (UInt32)mask);
} }
[System.CLSCompliant(false)] [System.CLSCompliant(false)]

View file

@ -1471,7 +1471,7 @@ namespace OpenTK.Graphics
internal extern static void StencilOpSeparate(OpenTK.Graphics.All face, OpenTK.Graphics.StencilOp sfail, OpenTK.Graphics.StencilOp dpfail, OpenTK.Graphics.StencilOp dppass); internal extern static void StencilOpSeparate(OpenTK.Graphics.All face, OpenTK.Graphics.StencilOp sfail, OpenTK.Graphics.StencilOp dpfail, OpenTK.Graphics.StencilOp dppass);
[System.Security.SuppressUnmanagedCodeSecurity()] [System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(GL.Library, EntryPoint = "glStencilFuncSeparate", ExactSpelling = true)] [System.Runtime.InteropServices.DllImport(GL.Library, EntryPoint = "glStencilFuncSeparate", ExactSpelling = true)]
internal extern static void StencilFuncSeparate(OpenTK.Graphics.StencilFunction frontfunc, OpenTK.Graphics.StencilFunction backfunc, Int32 @ref, UInt32 mask); internal extern static void StencilFuncSeparate(OpenTK.Graphics.StencilFace face, OpenTK.Graphics.StencilFunction func, Int32 @ref, UInt32 mask);
[System.Security.SuppressUnmanagedCodeSecurity()] [System.Security.SuppressUnmanagedCodeSecurity()]
[System.Runtime.InteropServices.DllImport(GL.Library, EntryPoint = "glStencilMaskSeparate", ExactSpelling = true)] [System.Runtime.InteropServices.DllImport(GL.Library, EntryPoint = "glStencilMaskSeparate", ExactSpelling = true)]
internal extern static void StencilMaskSeparate(OpenTK.Graphics.All face, UInt32 mask); internal extern static void StencilMaskSeparate(OpenTK.Graphics.All face, UInt32 mask);

View file

@ -1472,7 +1472,7 @@ namespace OpenTK.Graphics
internal delegate void StencilOpSeparate(OpenTK.Graphics.All face, OpenTK.Graphics.StencilOp sfail, OpenTK.Graphics.StencilOp dpfail, OpenTK.Graphics.StencilOp dppass); internal delegate void StencilOpSeparate(OpenTK.Graphics.All face, OpenTK.Graphics.StencilOp sfail, OpenTK.Graphics.StencilOp dpfail, OpenTK.Graphics.StencilOp dppass);
internal static StencilOpSeparate glStencilOpSeparate; internal static StencilOpSeparate glStencilOpSeparate;
[System.Security.SuppressUnmanagedCodeSecurity()] [System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void StencilFuncSeparate(OpenTK.Graphics.StencilFunction frontfunc, OpenTK.Graphics.StencilFunction backfunc, Int32 @ref, UInt32 mask); internal delegate void StencilFuncSeparate(OpenTK.Graphics.StencilFace face, OpenTK.Graphics.StencilFunction func, Int32 @ref, UInt32 mask);
internal static StencilFuncSeparate glStencilFuncSeparate; internal static StencilFuncSeparate glStencilFuncSeparate;
[System.Security.SuppressUnmanagedCodeSecurity()] [System.Security.SuppressUnmanagedCodeSecurity()]
internal delegate void StencilMaskSeparate(OpenTK.Graphics.All face, UInt32 mask); internal delegate void StencilMaskSeparate(OpenTK.Graphics.All face, UInt32 mask);

View file

@ -2,6 +2,13 @@ namespace OpenTK.Graphics
{ {
#pragma warning disable 1591 #pragma warning disable 1591
public enum StencilFace
{
Front = ((int)0X0404),
FrontAndBack = ((int)0X0408),
Back = ((int)0X0405),
}
public enum DrawElementsType public enum DrawElementsType
{ {
UnsignedByte = ((int)0X1401), UnsignedByte = ((int)0X1401),
@ -100,10 +107,12 @@ namespace OpenTK.Graphics
OneMinusConstantColorExt = ((int)0X8002), OneMinusConstantColorExt = ((int)0X8002),
SrcColor = ((int)0X0300), SrcColor = ((int)0X0300),
OneMinusSrcColor = ((int)0X0301), OneMinusSrcColor = ((int)0X0301),
OneMinusDstColor = ((int)0X0307),
ConstantAlphaExt = ((int)0X8003), ConstantAlphaExt = ((int)0X8003),
SrcAlpha = ((int)0X0302), SrcAlpha = ((int)0X0302),
DstAlpha = ((int)0X0304), DstColor = ((int)0X0306),
Zero = ((int)0), Zero = ((int)0),
DstAlpha = ((int)0X0304),
OneMinusConstantAlphaExt = ((int)0X8004), OneMinusConstantAlphaExt = ((int)0X8004),
} }
@ -112,9 +121,11 @@ namespace OpenTK.Graphics
ConstantColorExt = ((int)0X8001), ConstantColorExt = ((int)0X8001),
OneMinusSrcAlpha = ((int)0X0303), OneMinusSrcAlpha = ((int)0X0303),
One = ((int)1), One = ((int)1),
SrcAlphaSaturate = ((int)0X0308),
OneMinusConstantColorExt = ((int)0X8002),
OneMinusDstAlpha = ((int)0X0305), OneMinusDstAlpha = ((int)0X0305),
OneMinusConstantColorExt = ((int)0X8002),
SrcColor = ((int)0X0300),
SrcAlphaSaturate = ((int)0X0308),
OneMinusSrcColor = ((int)0X0301),
OneMinusDstColor = ((int)0X0307), OneMinusDstColor = ((int)0X0307),
ConstantAlphaExt = ((int)0X8003), ConstantAlphaExt = ((int)0X8003),
SrcAlpha = ((int)0X0302), SrcAlpha = ((int)0X0302),

View file

@ -344,9 +344,10 @@ namespace OpenTK.Graphics
static bool SupportsFunction(MethodInfo method) static bool SupportsFunction(MethodInfo method)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
#if false
lock (gl_lock) lock (gl_lock)
{ {
/*
if (function == null) if (function == null)
throw new ArgumentNullException("function"); throw new ArgumentNullException("function");
@ -362,9 +363,10 @@ namespace OpenTK.Graphics
return false; return false;
return f.GetValue(null) != null; return f.GetValue(null) != null;
*/
return false; return false;
} }
#endif
} }
#endregion #endregion
@ -641,7 +643,7 @@ namespace OpenTK.Graphics
#endregion #endregion
#region overloads using OpenTK.Math classes #region --- Overloads for OpenTK.Math ---
public static void Normal3(Vector3 normal) public static void Normal3(Vector3 normal)
{ {
@ -887,6 +889,44 @@ namespace OpenTK.Graphics
#endregion #endregion
#region public static void Rect(System.Drawing.RectangleF rect)
public static void Rect(System.Drawing.RectangleF rect)
{
GL.Rect(rect.Left, rect.Top, rect.Right, rect.Bottom);
}
#endregion
#region public static void Rect(ref System.Drawing.RectangleF rect)
[CLSCompliant(false)]
public static void Rect(ref System.Drawing.RectangleF rect)
{
GL.Rect(rect.Left, rect.Top, rect.Right, rect.Bottom);
}
#endregion
#region public static void Rect(System.Drawing.Rectangle rect)
public static void Rect(System.Drawing.Rectangle rect)
{
GL.Rect(rect.Left, rect.Top, rect.Right, rect.Bottom);
}
#endregion
#region public static void Rect(ref System.Drawing.Rectangle rect)
[CLSCompliant(false)]
public static void Rect(ref System.Drawing.Rectangle rect)
{
GL.Rect(rect.Left, rect.Top, rect.Right, rect.Bottom);
}
#endregion
#endregion #endregion
} }
} }

View file

@ -23,6 +23,10 @@ namespace OpenTK.Graphics
IGraphicsContext implementation; // The actual render context implementation for the underlying platform. IGraphicsContext implementation; // The actual render context implementation for the underlying platform.
List<IDisposable> dispose_queue = new List<IDisposable>(); List<IDisposable> dispose_queue = new List<IDisposable>();
bool disposed; bool disposed;
// Indicates that this context was created through external means, e.g. Tao.Sdl or GLWidget#.
// In this case, We'll assume that the external program will manage the lifetime of this
// context - we'll not destroy it manually.
bool is_external;
static bool share_contexts = true; static bool share_contexts = true;
static bool direct_rendering = true; static bool direct_rendering = true;
@ -30,17 +34,6 @@ namespace OpenTK.Graphics
// Maps OS-specific context handles to GraphicsContext weak references. // Maps OS-specific context handles to GraphicsContext weak references.
static Dictionary<ContextHandle, WeakReference> available_contexts = new Dictionary<ContextHandle, WeakReference>(); static Dictionary<ContextHandle, WeakReference> available_contexts = new Dictionary<ContextHandle, WeakReference>();
#region public GraphicsContext(DisplayMode mode, IWindowInfo window)
/// <summary>This method is obsolete.</summary>
/// <param name="mode"></param>
/// <param name="window"></param>
public GraphicsContext(DisplayMode mode, IWindowInfo window)
: this(mode.ToGraphicsMode(), window)
{ }
#endregion
#region public GraphicsContext(GraphicsMode format, IWindowInfo window) #region public GraphicsContext(GraphicsMode format, IWindowInfo window)
/// <summary> /// <summary>
@ -100,6 +93,42 @@ namespace OpenTK.Graphics
#endregion #endregion
private GraphicsContext()
{
}
/// <summary>
/// Attempts to create a GraphicsContext object from an existing OpenGL context.
/// </summary>
/// <param name="window">The window this context is bound to.</param>
/// <returns>A new GraphicsContext object, describing the current OpenGL context.</returns>
/// <remarks>
/// <para>Use this function to interoperate with OpenGL contexts created outside of OpenTK.</para>
/// <para>The new GraphicsContext is added to the list of available OpenTK contexts.
/// Make sure to call the Dispose() method once this context is destroyed.</para>
/// <para>You may not call this method more than once on the same context. Doing so will throw an exception.</para>
/// </remarks>
public static GraphicsContext CreateFromCurrentThread(IWindowInfo window)
{
Debug.Print("Creating context from current thread.");
GraphicsContext context = new GraphicsContext();
context.is_external = true;
if (Configuration.RunningOnWindows)
context.implementation = new OpenTK.Platform.Windows.WinGLContext(window);
else if (Configuration.RunningOnX11)
context.implementation = new OpenTK.Platform.X11.X11GLContext(window);
else
throw new PlatformNotSupportedException("Please, refer to http://www.opentk.com for more information.");
lock (context_lock)
{
available_contexts.Add((context as IGraphicsContextInternal).Context, new WeakReference(context));
}
return context;
}
#region void ContextDestroyed(IGraphicsContext context, EventArgs e) #region void ContextDestroyed(IGraphicsContext context, EventArgs e)
/// <summary> /// <summary>
@ -377,7 +406,7 @@ namespace OpenTK.Graphics
available_contexts.Remove((this as IGraphicsContextInternal).Context); available_contexts.Remove((this as IGraphicsContextInternal).Context);
} }
if (manual) if (manual && !is_external)
{ {
if (implementation != null) if (implementation != null)
implementation.Dispose(); implementation.Dispose();

View file

@ -0,0 +1,49 @@
using System;
using System.Collections.Generic;
using System.Text;
using OpenTK.Math;
namespace OpenTK.Input
{
#if false
/// <summary>
/// Represents a joystick device and provides methods to query its state.
/// </summary>
public class JoystickDevice : IInputDevice
{
string description;
Vector2[] axis_position;
#region --- IInputDevice Members ---
/// <summary>
/// Gets a string describing this JoystickDevice.
/// </summary>
public string Description
{
get { return description; }
internal set { description = value; }
}
/// <summary>
/// Gets a value indicating the InputDeviceType of this InputDevice.
/// </summary>
public InputDeviceType DeviceType
{
get { return InputDeviceType.HID; }
}
#endregion
#region --- Public Methods ---
//public Vector2 Axis1
//{
// get { return axis_position.Clone(); }
// internal set {
//}
#endregion
}
#endif
}

View file

@ -43,7 +43,7 @@ namespace OpenTK.Input
#region public InputDeviceType DeviceType #region public InputDeviceType DeviceType
/// <summary> /// <summary>
/// Gets an value indicating the InputDeviceType of this InputDevice. /// Gets a value indicating the InputDeviceType of this InputDevice.
/// </summary> /// </summary>
public InputDeviceType DeviceType public InputDeviceType DeviceType
{ {

View file

@ -16,8 +16,9 @@ namespace OpenTK.Math
/// <summary> /// <summary>
/// Represents a 4x4 Matrix /// Represents a 4x4 Matrix
/// </summary> /// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Matrix4 public struct Matrix4 : IEquatable<Matrix4>
{ {
#region Fields #region Fields
@ -152,9 +153,14 @@ namespace OpenTK.Math
return Matrix4.Mult(left, right); return Matrix4.Mult(left, right);
} }
public float get(int x, int y) public static bool operator ==(Matrix4 left, Matrix4 right)
{ {
throw new NotImplementedException(); return left.Equals(right);
}
public static bool operator !=(Matrix4 left, Matrix4 right)
{
return !left.Equals(right);
} }
#endregion #endregion
@ -580,5 +586,51 @@ namespace OpenTK.Math
} }
#endregion #endregion
#region public override int GetHashCode()
/// <summary>
/// Returns the hashcode for this instance.
/// </summary>
/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
public override int GetHashCode()
{
return Row0.GetHashCode() ^ Row1.GetHashCode() ^ Row2.GetHashCode() ^ Row3.GetHashCode();
}
#endregion
#region public override bool Equals(object obj)
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <param name="obj">The object to compare to.</param>
/// <returns>True if the instances are equal; false otherwise.</returns>
public override bool Equals(object obj)
{
if (!(obj is Matrix4))
return false;
return this.Equals((Matrix4)obj);
}
#endregion
#region IEquatable<Matrix4> Members
/// <summary>Indicates whether the current matrix is equal to another matrix.</summary>
/// <param name="matrix">An matrix to compare with this matrix.</param>
/// <returns>true if the current matrix is equal to the matrix parameter; otherwise, false.</returns>
public bool Equals(Matrix4 other)
{
return
Row0 == other.Row0 &&
Row1 == other.Row1 &&
Row2 == other.Row2 &&
Row3 == other.Row3;
}
#endregion
} }
} }

View file

@ -16,6 +16,7 @@ namespace OpenTK.Math
/// <summary> /// <summary>
/// Represents a Quaternion /// Represents a Quaternion
/// </summary> /// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Quaternion public struct Quaternion
{ {

View file

@ -19,8 +19,9 @@ namespace OpenTK.Math
/// <remarks> /// <remarks>
/// The Vector2 structure is suitable for interoperation with unmanaged code requiring two consecutive floats. /// The Vector2 structure is suitable for interoperation with unmanaged code requiring two consecutive floats.
/// </remarks> /// </remarks>
[Serializable]
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Vector2 public struct Vector2 : IEquatable<Vector2>
{ {
#region Fields #region Fields
@ -267,6 +268,16 @@ namespace OpenTK.Math
return vec; return vec;
} }
public static bool operator ==(Vector2 left, Vector2 right)
{
return left.Equals(right);
}
public static bool operator !=(Vector2 left, Vector2 right)
{
return !left.Equals(right);
}
[CLSCompliant(false)] [CLSCompliant(false)]
unsafe public static explicit operator float*(Vector2 v) unsafe public static explicit operator float*(Vector2 v)
{ {
@ -615,5 +626,49 @@ namespace OpenTK.Math
} }
#endregion #endregion
#region public override int GetHashCode()
/// <summary>
/// Returns the hashcode for this instance.
/// </summary>
/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
public override int GetHashCode()
{
return X.GetHashCode() ^ Y.GetHashCode();
}
#endregion
#region public override bool Equals(object obj)
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <param name="obj">The object to compare to.</param>
/// <returns>True if the instances are equal; false otherwise.</returns>
public override bool Equals(object obj)
{
if (!(obj is Vector2))
return false;
return this.Equals((Vector2)obj);
}
#endregion
#region IEquatable<Vector2> Members
/// <summary>Indicates whether the current vector is equal to another vector.</summary>
/// <param name="vector">A vector to compare with this vector.</param>
/// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
public bool Equals(Vector2 other)
{
return
X == other.X &&
Y == other.Y;
}
#endregion
} }
} }

View file

@ -16,8 +16,9 @@ namespace OpenTK.Math
/// <summary> /// <summary>
/// Represents a three-dimensional vector. /// Represents a three-dimensional vector.
/// </summary> /// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Vector3 public struct Vector3 : IEquatable<Vector3>
{ {
#region Fields #region Fields
@ -97,6 +98,32 @@ namespace OpenTK.Math
#region Functions #region Functions
#region This property
public float this[int index]
{
get
{
switch (index)
{
case 0: return X;
case 1: return Y;
case 2: return Z;
default: throw new ArgumentOutOfRangeException("index", index, "Should be 0, 1 or 2.");
}
/*
unsafe
{
fixed (float* ptr = &this.X)
return *(ptr + index);
}
*/
}
}
#endregion
#region public float Length #region public float Length
/// <summary> /// <summary>
@ -257,23 +284,14 @@ namespace OpenTK.Math
return vec; return vec;
} }
public float get(int index) public static bool operator ==(Vector3 left, Vector3 right)
{ {
switch (index) return left.Equals(right);
{ }
case 0: return X;
case 1: return Y;
case 2: return Z;
default: throw new ArgumentOutOfRangeException("index", index, "Should be 0, 1 or 2.");
}
/*
unsafe
{
fixed (float* ptr = &this.X)
return *(ptr + index);
}
*/ public static bool operator !=(Vector3 left, Vector3 right)
{
return !left.Equals(right);
} }
#endregion #endregion
@ -810,5 +828,50 @@ namespace OpenTK.Math
} }
#endregion #endregion
}
#region public override int GetHashCode()
/// <summary>
/// Returns the hashcode for this instance.
/// </summary>
/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
public override int GetHashCode()
{
return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode();
}
#endregion
#region public override bool Equals(object obj)
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <param name="obj">The object to compare to.</param>
/// <returns>True if the instances are equal; false otherwise.</returns>
public override bool Equals(object obj)
{
if (!(obj is Vector3))
return false;
return this.Equals((Vector3)obj);
}
#endregion
#region IEquatable<Vector3> Members
/// <summary>Indicates whether the current vector is equal to another vector.</summary>
/// <param name="vector">A vector to compare with this vector.</param>
/// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
public bool Equals(Vector3 other)
{
return
X == other.X &&
Y == other.Y &&
Z == other.Z;
}
#endregion
}
} }

View file

@ -16,8 +16,9 @@ namespace OpenTK.Math
/// <summary> /// <summary>
/// Represents a four-dimensional vector. /// Represents a four-dimensional vector.
/// </summary> /// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential)] [StructLayout(LayoutKind.Sequential)]
public struct Vector4 public struct Vector4 : IEquatable<Vector4>
{ {
#region Fields #region Fields
@ -276,6 +277,16 @@ namespace OpenTK.Math
return vec; return vec;
} }
public static bool operator ==(Vector4 left, Vector4 right)
{
return left.Equals(right);
}
public static bool operator !=(Vector4 left, Vector4 right)
{
return !left.Equals(right);
}
[CLSCompliant(false)] [CLSCompliant(false)]
unsafe public static explicit operator float*(Vector4 v) unsafe public static explicit operator float*(Vector4 v)
{ {
@ -682,5 +693,51 @@ namespace OpenTK.Math
} }
#endregion #endregion
}
#region public override int GetHashCode()
/// <summary>
/// Returns the hashcode for this instance.
/// </summary>
/// <returns>A System.Int32 containing the unique hashcode for this instance.</returns>
public override int GetHashCode()
{
return X.GetHashCode() ^ Y.GetHashCode() ^ Z.GetHashCode() ^ W.GetHashCode();
}
#endregion
#region public override bool Equals(object obj)
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>
/// <param name="obj">The object to compare to.</param>
/// <returns>True if the instances are equal; false otherwise.</returns>
public override bool Equals(object obj)
{
if (!(obj is Vector4))
return false;
return this.Equals((Vector4)obj);
}
#endregion
#region IEquatable<Vector4> Members
/// <summary>Indicates whether the current vector is equal to another vector.</summary>
/// <param name="vector">A vector to compare with this vector.</param>
/// <returns>true if the current vector is equal to the vector parameter; otherwise, false.</returns>
public bool Equals(Vector4 other)
{
return
X == other.X &&
Y == other.Y &&
Z == other.Z &&
W == other.W;
}
#endregion
}
} }

View file

@ -0,0 +1,120 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing details.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Reflection;
using System.Diagnostics;
namespace OpenTK.Platform
{
internal static class GdiPlus
{
static IGdiPlusInternals internals;
const string gdi_plus_library = "gdiplus.dll";
#region --- Constructors ---
static GdiPlus()
{
if (Configuration.RunningOnWindows)
internals = new Windows.WinGdiPlusInternals();
else
internals = new X11.X11GdiPlusInternals();
}
#endregion
#region --- Public Methods ---
public static IntPtr GetNativeGraphics(System.Drawing.Graphics graphics)
{
return internals.GetNativeGraphics(graphics);
}
public static IntPtr GetNativeFont(Font font)
{
return internals.GetNativeFont(font);
}
public static IntPtr GetNativeStringFormat(StringFormat format)
{
return internals.GetNativeStringFormat(format);
}
public static int MaxMeasurableCharacterRanges
{
get
{
return 32; // This is a GDI+ limitation. TODO: Can we query this somehow?
}
}
[DllImport(gdi_plus_library, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true, EntryPoint = "GdipSetStringFormatMeasurableCharacterRanges")]
public static extern int SetStringFormatMeasurableCharacterRanges(HandleRef format, int rangeCount, [In, Out] CharacterRange[] range);
[DllImport(gdi_plus_library, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true, EntryPoint = "GdipGetStringFormatMeasurableCharacterRangeCount")]
public static extern int GetStringFormatMeasurableCharacterRangeCount(HandleRef format, out int count);
[DllImport(gdi_plus_library, CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true, EntryPoint = "GdipMeasureCharacterRanges")]
public static extern int MeasureCharacterRanges(HandleRef graphics, string textString, int length, HandleRef font, ref RectangleF layoutRect, HandleRef stringFormat, int characterCount, [In, Out] IntPtr[] region);
[DllImport("gdiplus.dll", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true, EntryPoint = "GdipGetRegionBounds")]
public static extern int GetRegionBounds(IntPtr region, HandleRef graphics, ref RectangleF gprectf);
[DllImport("gdiplus.dll", EntryPoint = "GdipCreateRegion", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
public static extern int CreateRegion(out IntPtr region);
[DllImport("gdiplus.dll", EntryPoint = "GdipDeleteRegion", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
public static extern int DeleteRegion(IntPtr region);
#endregion
#if false
[StructLayout(LayoutKind.Sequential)]
internal struct GPRECTF
{
internal float X;
internal float Y;
internal float Width;
internal float Height;
internal GPRECTF(float x, float y, float width, float height)
{
this.X = x;
this.Y = y;
this.Width = width;
this.Height = height;
}
internal GPRECTF(RectangleF rect)
{
this.X = rect.X;
this.Y = rect.Y;
this.Width = rect.Width;
this.Height = rect.Height;
}
internal SizeF SizeF
{
get
{
return new SizeF(this.Width, this.Height);
}
}
internal RectangleF ToRectangleF()
{
return new RectangleF(this.X, this.Y, this.Width, this.Height);
}
}
#endif
}
}

View file

@ -0,0 +1,29 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
namespace OpenTK.Platform
{
// Provides methods to access internal GdiPlus fields. This is necessary for
// managed <-> native GdiPlus interoperability.
// Note that the fields are named differently between .Net and Mono.
// GdiPlus is considered deprecated by Microsoft - it is highly unlikely that
// future framework upgrades will break this code, but it is something to
// keep in mind.
interface IGdiPlusInternals
{
IntPtr GetNativeGraphics(System.Drawing.Graphics graphics);
IntPtr GetNativeFont(System.Drawing.Font font);
IntPtr GetNativeStringFormat(System.Drawing.StringFormat format);
}
}

View file

@ -149,7 +149,7 @@ namespace OpenTK.Platform
return false; return false;
} }
FieldInfo f = type.GetField(extension, BindingFlags.Static | BindingFlags.NonPublic); FieldInfo f = extensions_class.GetField(extension, BindingFlags.Static | BindingFlags.NonPublic);
if (f == null) if (f == null)
{ {
Debug.Print("Extension \"", extension, "\" not found in ", type.ToString()); Debug.Print("Extension \"", extension, "\" not found in ", type.ToString());
@ -212,6 +212,132 @@ namespace OpenTK.Platform
} }
#endregion
#region --- Creating an Graphics Context ---
#region --- CreateWindowInfo ---
/// <summary>
/// Creates GraphicsContext and IWindowInfo objects for a WinForms control.
/// </summary>
/// <param name="cntrl"></param>
/// <param name="context"></param>
/// <param name="info"></param>
/// <param name="mode"></param>
public static void CreateGraphicsContext(Graphics.GraphicsMode mode, Control cntrl, out Graphics.GraphicsContext context, out IWindowInfo info)
{
CreateGraphicsContext(mode, cntrl.Handle, out context, out info);
}
/// <summary>
/// Creates GraphicsContext and IWindowInfo objects for a WinForms control.
/// </summary>
/// <param name="cntrlHandle"></param>
/// <param name="context"></param>
/// <param name="info"></param>
/// <param name="mode"></param>
public static void CreateGraphicsContext(Graphics.GraphicsMode mode, IntPtr cntrlHandle, out Graphics.GraphicsContext context, out IWindowInfo info)
{
info = CreateWindowInfo(mode, cntrlHandle);
context = new Graphics.GraphicsContext(mode, info);
context.MakeCurrent(info);
(context as OpenTK.Graphics.IGraphicsContextInternal).LoadAll();
}
/// <summary>
/// Creates an object which implements the IWindowInfo interface for the platform
/// currently running on. This will create a handle for the control, so it is not
/// recommended that this be called in the constructor of a custom control.
/// </summary>
/// <param name="cntrl"></param>
/// <returns></returns>
public static IWindowInfo CreateWindowInfo(Graphics.GraphicsMode mode, Control cntrl)
{
return CreateWindowInfo(mode, cntrl.Handle);
}
/// <summary>
/// Creates an object which implements the IWindowInfo interface for the platform
/// currently running on.
/// </summary>
/// <param name="controlHandle">The handle to the control, obtained from Control.Handle.</param>
/// <returns></returns>
public static IWindowInfo CreateWindowInfo(Graphics.GraphicsMode mode, IntPtr controlHandle)
{
if (Configuration.RunningOnWindows) return CreateWinWindowInfo(controlHandle);
else if (Configuration.RunningOnX11) return CreateX11WindowInfo(mode, controlHandle);
else if (Configuration.RunningOnOSX) return CreateOSXWindowInfo(controlHandle);
else
throw new PlatformNotSupportedException("Refer to http://www.opentk.com for more information.");
}
#endregion
#region --- X11 Platform-specific implementation ---
private static IWindowInfo CreateX11WindowInfo(Graphics.GraphicsMode mode, IntPtr controlHandle)
{
Platform.X11.X11WindowInfo window = new OpenTK.Platform.X11.X11WindowInfo();
Type xplatui = Type.GetType("System.Windows.Forms.XplatUIX11, System.Windows.Forms");
if (xplatui == null) throw new PlatformNotSupportedException(
"System.Windows.Forms.XplatUIX11 missing. Unsupported platform or Mono runtime version, aborting.");
window.WindowHandle = controlHandle;
// get the required handles from the X11 API.
window.Display = (IntPtr)GetStaticFieldValue(xplatui, "DisplayHandle");
window.RootWindow = (IntPtr)GetStaticFieldValue(xplatui, "RootWindow");
window.Screen = (int)GetStaticFieldValue(xplatui, "ScreenNo");
// get the X11 Visual info for the display.
Platform.X11.XVisualInfo info = new Platform.X11.XVisualInfo();
info.visualid = mode.Index;
int dummy;
window.VisualInfo = (Platform.X11.XVisualInfo)Marshal.PtrToStructure(
Platform.X11.Functions.XGetVisualInfo(window.Display, Platform.X11.XVisualInfoMask.ID,
ref info, out dummy), typeof(Platform.X11.XVisualInfo));
// set the X11 colormap.
SetStaticFieldValue(xplatui, "CustomVisual", window.VisualInfo.visual);
SetStaticFieldValue(xplatui, "CustomColormap",
Platform.X11.Functions.XCreateColormap(window.Display, window.RootWindow, window.VisualInfo.visual, 0));
return window;
}
#endregion
#region --- Windows Platform-specific implementation ---
private static IWindowInfo CreateWinWindowInfo(IntPtr controlHandle)
{
return new OpenTK.Platform.Windows.WinWindowInfo(controlHandle, null);
}
#endregion
#region --- Mac OS X Platform-specific implementation ---
private static IWindowInfo CreateOSXWindowInfo(IntPtr controlHandle)
{
throw new PlatformNotSupportedException("Refer to http://www.opentk.com for more information.");
}
#endregion
#region --- Utility functions for reading/writing non-public static fields through reflection ---
private static object GetStaticFieldValue(Type type, string fieldName)
{
return type.GetField(fieldName,
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).GetValue(null);
}
private static void SetStaticFieldValue(Type type, string fieldName, object value)
{
type.GetField(fieldName,
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic).SetValue(null, value);
}
#endregion
#endregion #endregion
} }
} }

View file

@ -1434,6 +1434,8 @@ namespace OpenTK.Platform.Windows
#region PixelFormatDescriptor #region PixelFormatDescriptor
#pragma warning disable 0169
/// <summary> /// <summary>
/// Describes a pixel format. It is used when interfacing with the WINAPI to create a new Context. /// Describes a pixel format. It is used when interfacing with the WINAPI to create a new Context.
/// Found in WinGDI.h /// Found in WinGDI.h
@ -1469,6 +1471,8 @@ namespace OpenTK.Platform.Windows
internal int DamageMask; internal int DamageMask;
} }
#pragma warning restore 0169
#endregion #endregion
#region internal class LayerPlaneDescriptor #region internal class LayerPlaneDescriptor

View file

@ -144,7 +144,7 @@ namespace OpenTK.Platform.Windows
// TODO: Not 100% reliable, when both keys are pressed at once. // TODO: Not 100% reliable, when both keys are pressed at once.
if (ShiftRightScanCode != 0) if (ShiftRightScanCode != 0)
{ {
if ((((int)msg.LParam >> 16) & 0xFF) == ShiftRightScanCode) if (((msg.LParam.ToInt32() >> 16) & 0xFF) == ShiftRightScanCode)
keyboard[Input.Key.ShiftRight] = pressed; keyboard[Input.Key.ShiftRight] = pressed;
else else
keyboard[Input.Key.ShiftLeft] = pressed; keyboard[Input.Key.ShiftLeft] = pressed;

View file

@ -90,6 +90,17 @@ namespace OpenTK.Platform.Windows
} }
} }
public WinGLContext(IWindowInfo window)
{
if (window == null) throw new ArgumentNullException("window");
renderContext = Wgl.GetCurrentContext();
if (renderContext == IntPtr.Zero)
throw new InvalidOperationException("No OpenGL context is current in the calling thread.");
currentWindow = (WinWindowInfo)window;
}
#endregion #endregion
#region --- IGraphicsContext Members --- #region --- IGraphicsContext Members ---

View file

@ -0,0 +1,53 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Reflection;
namespace OpenTK.Platform.Windows
{
class WinGdiPlusInternals : IGdiPlusInternals
{
static readonly PropertyInfo native_graphics_property, native_font_property;
static readonly FieldInfo native_string_format_field;
static WinGdiPlusInternals()
{
native_graphics_property =
typeof(System.Drawing.Graphics).GetProperty("NativeGraphics", BindingFlags.Instance | BindingFlags.NonPublic);
native_font_property =
typeof(System.Drawing.Font).GetProperty("NativeFont", BindingFlags.Instance | BindingFlags.NonPublic);
native_string_format_field =
typeof(System.Drawing.StringFormat).GetField("nativeFormat", BindingFlags.Instance | BindingFlags.NonPublic);
}
#region --- IGdiPlusInternals Members ---
public IntPtr GetNativeGraphics(System.Drawing.Graphics graphics)
{
return (IntPtr)native_graphics_property.GetValue(graphics, null);
}
public IntPtr GetNativeFont(Font font)
{
return (IntPtr)native_font_property.GetValue(font, null);
}
public IntPtr GetNativeStringFormat(StringFormat format)
{
return (IntPtr)native_string_format_field.GetValue(format);
}
#endregion
}
}

View file

@ -4,9 +4,8 @@ using System.Text;
namespace OpenTK.Platform.Windows namespace OpenTK.Platform.Windows
{ {
/// <internal />
/// <summary>Describes a win32 window.</summary> /// <summary>Describes a win32 window.</summary>
internal sealed class WinWindowInfo : IWindowInfo public sealed class WinWindowInfo : IWindowInfo
{ {
IntPtr handle, dc; IntPtr handle, dc;
WinWindowInfo parent; WinWindowInfo parent;

View file

@ -39,7 +39,7 @@ namespace OpenTK.Platform.X11
GraphicsContext.GetCurrentContext = X11GLContext.GetCurrentContext; GraphicsContext.GetCurrentContext = X11GLContext.GetCurrentContext;
} }
internal X11GLContext(GraphicsMode mode, IWindowInfo info, IGraphicsContext shared, bool directRendering) public X11GLContext(GraphicsMode mode, IWindowInfo info, IGraphicsContext shared, bool directRendering)
{ {
//if (mode == null) mode = GraphicsMode.Default; //if (mode == null) mode = GraphicsMode.Default;
if (info == null) throw new ArgumentNullException("info", "Should point to a valid window."); if (info == null) throw new ArgumentNullException("info", "Should point to a valid window.");
@ -52,6 +52,17 @@ namespace OpenTK.Platform.X11
CreateContext(shared, directRendering, currentWindow); CreateContext(shared, directRendering, currentWindow);
} }
public X11GLContext(IWindowInfo window)
{
if (window == null) throw new ArgumentNullException("window");
//renderContext = Glx.GetCurrentContext();
//if (renderContext == IntPtr.Zero)
// throw new InvalidOperationException("No OpenGL context is current in the calling thread.");
//currentWindow = window;
}
#endregion #endregion
#region --- Private Methods --- #region --- Private Methods ---

View file

@ -0,0 +1,52 @@
#region --- License ---
/* Licensed under the MIT/X11 license.
* Copyright (c) 2006-2008 the OpenTK Team.
* This notice may not be removed from any source distribution.
* See license.txt for licensing detailed licensing details.
*/
#endregion
using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Reflection;
namespace OpenTK.Platform.X11
{
class X11GdiPlusInternals : IGdiPlusInternals
{
static readonly PropertyInfo native_graphics_property, native_font_property, native_string_format_property;
static X11GdiPlusInternals()
{
native_graphics_property =
typeof(System.Drawing.Graphics).GetProperty("NativeObject", BindingFlags.Instance | BindingFlags.NonPublic);
native_font_property =
typeof(System.Drawing.Font).GetProperty("NativeObject", BindingFlags.Instance | BindingFlags.NonPublic);
native_string_format_property =
typeof(System.Drawing.StringFormat).GetProperty("NativeObject", BindingFlags.Instance | BindingFlags.NonPublic);
}
#region --- IGdiPlusInternals Members ---
public IntPtr GetNativeGraphics(System.Drawing.Graphics graphics)
{
return (IntPtr)native_graphics_property.GetValue(graphics, null);
}
public IntPtr GetNativeFont(Font font)
{
return (IntPtr)native_font_property.GetValue(font, null);
}
public IntPtr GetNativeStringFormat(StringFormat format)
{
return (IntPtr)native_string_format_property.GetValue(format, null);
}
#endregion
}
}

View file

@ -86,7 +86,7 @@ namespace OpenTK.Audio
} }
} }
} }
catch (Exception e) catch (Exception)
{ {
s.Close(); s.Close();
throw; throw;

View file

@ -191,7 +191,7 @@ namespace OpenTK.Audio
//return new SoundData(decoded_data, new SoundFormat(channels, bits_per_sample, sample_rate)); //return new SoundData(decoded_data, new SoundFormat(channels, bits_per_sample, sample_rate));
return decoded_data; return decoded_data;
} }
catch (AudioReaderException e) catch (AudioReaderException)
{ {
reader.Close(); reader.Close();
throw; throw;

View file

@ -16,13 +16,11 @@ namespace OpenTK.Graphics
/// <summary> /// <summary>
/// Represents a single character of a specific Font. /// Represents a single character of a specific Font.
/// </summary> /// </summary>
class Glyph : IPackable<Glyph> struct Glyph : IPackable<Glyph>
{ {
char character; char character;
Font font; Font font;
int width; SizeF size;
static Bitmap bmp = new Bitmap(1, 1);
object obj = new object();
#region --- Constructors --- #region --- Constructors ---
@ -31,16 +29,19 @@ namespace OpenTK.Graphics
/// </summary> /// </summary>
/// <param name="c">The character to represent.</param> /// <param name="c">The character to represent.</param>
/// <param name="f">The Font of the character.</param> /// <param name="f">The Font of the character.</param>
public Glyph(char c, Font f) public Glyph(char c, Font f, SizeF s)
{ {
if (f == null) if (f == null)
throw new ArgumentNullException("f", "You must specify a valid font"); throw new ArgumentNullException("f", "You must specify a valid font");
character = c; character = c;
font = f; font = f;
size = s;
} }
#endregion #endregion
#region --- Public Methods ---
#region public char Character #region public char Character
/// <summary> /// <summary>
@ -73,7 +74,52 @@ namespace OpenTK.Graphics
#endregion #endregion
#region IPackable<T> Members #region public override bool Equals(object obj)
/// <summary>
/// Checks whether the given object is equal (memberwise) to the current Glyph.
/// </summary>
/// <param name="obj">The obj to check.</param>
/// <returns>True, if the object is identical to the current Glyph.</returns>
public override bool Equals(object obj)
{
if (obj is Glyph)
return this.Equals((Glyph)obj);
return base.Equals(obj);
}
#endregion
#region public override string ToString()
/// <summary>
/// Describes this Glyph object.
/// </summary>
/// <returns>Returns a System.String describing this Glyph.</returns>
public override string ToString()
{
return String.Format("'{0}', {1} {2}, {3} {4}, ({5}, {6})", Character, Font.Name, font.Style, font.Size, font.Unit, Width, Height);
}
#endregion
#region public override int GetHashCode()
/// <summary>
/// Calculates the hashcode for this Glyph.
/// </summary>
/// <returns>A System.Int32 containing a hashcode that uniquely identifies this Glyph.</returns>
public override int GetHashCode()
{
//return character.GetHashCode() ^ font.Style.GetHashCode() ^ font.Size.GetHashCode() ^ font.Unit.GetHashCode();
return character.GetHashCode() ^ font.GetHashCode() ^ size.GetHashCode();
}
#endregion
#endregion
#region --- IPackable<T> Members ---
/// <summary> /// <summary>
/// Gets an integer representing the width of the Glyph in pixels. /// Gets an integer representing the width of the Glyph in pixels.
@ -82,17 +128,7 @@ namespace OpenTK.Graphics
{ {
get get
{ {
if (width == 0) return (int)System.Math.Ceiling(size.Width);
{
lock (obj)
using (Graphics gfx = Graphics.FromImage(bmp))
{
float w = gfx.MeasureString(Character.ToString(), font).Width;
width = (int)System.Math.Ceiling(w);
}
}
return width;
} }
} }
@ -103,30 +139,13 @@ namespace OpenTK.Graphics
{ {
get get
{ {
return font.Height; return (int)System.Math.Ceiling(size.Height);
} }
} }
#endregion #endregion
public override bool Equals(object obj) #region --- IEquatable<Glyph> Members ---
{
if (obj is Glyph)
return this.Equals((Glyph)obj);
return base.Equals(obj);
}
public override string ToString()
{
return String.Format("'{0}', {1} {2}, {3} {4}", Character, Font.Name, font.Style, font.Size, font.Unit);
}
public override int GetHashCode()
{
return character.GetHashCode() ^ font.Style.GetHashCode() ^ font.Size.GetHashCode() ^ font.Unit.GetHashCode();
}
#region IEquatable<Glyph> Members
/// <summary> /// <summary>
/// Compares the current Glyph with the given Glyph. /// Compares the current Glyph with the given Glyph.

View file

@ -15,10 +15,31 @@ namespace OpenTK.Graphics
/// <summary> /// <summary>
/// Defines the interface for TextPrinter implementations. /// Defines the interface for TextPrinter implementations.
/// </summary> /// </summary>
interface ITextPrinterImplementation public interface ITextPrinterImplementation
{ {
TextHandle Load(Vector2[] vertices, ushort[] indices, int index_count); /// <summary>
/// Caches a text fragment for future use.
/// </summary>
/// <param name="vertices">The vertex array for the text fragment.</param>
/// <param name="indices">The index array for the text fragment. Please use the indexCount parameter
/// instead of indices.Count, as the indices array may be larger than necessary for performance reasons.</param>
/// <param name="indexCount">The actual number of indices in the text fragment.</param>
/// <returns>A TextHandle that can be used to draw the text fragment.</returns>
TextHandle Load(Vector2[] vertices, ushort[] indices, int indexCount);
/// <summary>
/// Draws the specified cached text fragment.
/// </summary>
/// <param name="handle">The TextHandle corresponding to the desired text fragment.</param>
void Draw(TextHandle handle); void Draw(TextHandle handle);
void Draw(Vector2[] vertices, ushort[] indices, int index_count);
/// <summary>
/// Draws a text fragment, without caching.
/// </summary>
/// <param name="vertices">The vertex array for the text fragment.</param>
/// <param name="indices">The index array for the text fragment. Please use the indexCount parameter
/// instead of indices.Count, as the indices array may be larger than necessary for performance reasons.</param>
/// <param name="indexCount">The actual number of indices in the text fragment.</param>
void Draw(Vector2[] vertices, ushort[] indices, int indexCount);
} }
} }

View file

@ -13,20 +13,39 @@ namespace OpenTK.Graphics
/// <summary> /// <summary>
/// Represents a handle to cached text. /// Represents a handle to cached text.
/// </summary> /// </summary>
public class TextHandle : IDisposable public abstract class TextHandle : IDisposable
{ {
internal TextHandle(int handle) /// <summary>
/// Constructs a new TextHandle,
/// </summary>
/// <param name="handle"></param>
public TextHandle(int handle)
{ {
Handle = handle; Handle = handle;
} }
private int handle;
protected TextureFont font;
protected bool disposed;
/// <summary> /// <summary>
/// The handle of the cached text. Call the OpenTK.Graphics.ITextPrinter.Draw() method /// Gets the handle of the cached text run. Call the OpenTK.Graphics.ITextPrinter.Draw() method
/// to draw the text represented by this TextHandle. /// to draw the text represented by this TextHandle.
/// </summary> /// </summary>
public readonly int Handle; public int Handle
internal TextureFont font; {
protected bool disposed; get { return handle; }
protected set { handle = value; }
}
/// <summary>
/// Gets the TextureFont used for this text run.
/// </summary>
public TextureFont Font
{
get { return font; }
internal set { font = value; }
}
#region public override string ToString() #region public override string ToString()

View file

@ -37,14 +37,23 @@ namespace OpenTK.Graphics
// Interleaved, vertex, texcoord, vertex, etc... Starts with 8 chars, will expand as needed. // Interleaved, vertex, texcoord, vertex, etc... Starts with 8 chars, will expand as needed.
Vector2[] vertices = new Vector2[8 * 8]; Vector2[] vertices = new Vector2[8 * 8];
ushort[] indices = new ushort[6 * 8]; ushort[] indices = new ushort[6 * 8];
IList<RectangleF> ranges = new List<RectangleF>();
#region --- Constructor ---
#region --- Constructors ---
/// <summary> /// <summary>
/// Constructs a new TextPrinter object. /// Constructs a new TextPrinter object.
/// </summary> /// </summary>
public TextPrinter() { } public TextPrinter() { }
public TextPrinter(ITextPrinterImplementation implementation)
{
if (implementation == null)
throw new ArgumentNullException("implementation");
printer = implementation;
}
#endregion #endregion
#region --- Private Members --- #region --- Private Members ---
@ -155,7 +164,7 @@ namespace OpenTK.Graphics
PerformLayout(text, font, width, wordWarp, alignment, rightToLeft, ref vertices, ref indices, out num_indices); PerformLayout(text, font, width, wordWarp, alignment, rightToLeft, ref vertices, ref indices, out num_indices);
handle = Printer.Load(vertices, indices, num_indices); handle = Printer.Load(vertices, indices, num_indices);
handle.font = font; handle.Font = font;
} }
#endregion #endregion
@ -175,11 +184,11 @@ namespace OpenTK.Graphics
if (wordWarp || rightToLeft || alignment != StringAlignment.Near) if (wordWarp || rightToLeft || alignment != StringAlignment.Near)
throw new NotImplementedException(); throw new NotImplementedException();
while (8 * text.Length > vertices.Length) if (8 * text.Length > vertices.Length)
vertices = new Vector2[vertices.Length << 1]; vertices = new Vector2[Math.Functions.NextPowerOfTwo(8 * text.Length)];
while (6 * text.Length > indices.Length) if (6 * text.Length > indices.Length)
indices = new ushort[indices.Length << 1]; indices = new ushort[Math.Functions.NextPowerOfTwo(6 * text.Length)];
num_indices = 6 * text.Length; num_indices = 6 * text.Length;
@ -187,65 +196,59 @@ namespace OpenTK.Graphics
//ushort[] indices = new ushort[6 * text.Length]; //ushort[] indices = new ushort[6 * text.Length];
float x_pos = 0, y_pos = 0; float x_pos = 0, y_pos = 0;
ushort i = 0, index_count = 0, vertex_count = 0, last_break_point = 0; ushort i = 0, index_count = 0, vertex_count = 0, last_break_point = 0;
Box2 rect = new Box2(); RectangleF rect = new RectangleF();
float char_width, char_height, measured_width, measured_height; float char_width, char_height;
int texture; int texture;
font.LoadGlyphs(text); font.LoadGlyphs(text);
// Every character comprises of 4 vertices, forming two triangles. We generate an index array which // Every character comprises of 4 vertices, forming two triangles. We generate an index array which
// indexes vertices in a triangle-strip fashion. To create a single strip for the whole string, we // indexes vertices in a triangle-list fashion.
// need to add a degenerate triangle (0 height) to connect the last vertex of the previous line with
// the first vertex of the next line.
// This algorithm works for left-to-right scripts. // This algorithm works for left-to-right scripts.
if (alignment == StringAlignment.Near && !rightToLeft || alignment == StringAlignment.Far && rightToLeft) if (alignment == StringAlignment.Near && !rightToLeft || alignment == StringAlignment.Far && rightToLeft)
{ {
foreach (char c in text) font.MeasureText(text, SizeF.Empty, null, ranges);
int current = 0;
foreach (RectangleF range in ranges)
{ {
char c = text[current++];
if (Char.IsSeparator(c)) if (Char.IsSeparator(c))
last_break_point = index_count; last_break_point = index_count;
if (c != '\n' && c != '\r') x_pos = range.X;
{ y_pos = range.Y;
font.GlyphData(c, out char_width, out char_height, out rect, out texture);
vertices[vertex_count].X = x_pos; // Vertex font.GlyphData(c, out char_width, out char_height, out rect, out texture);
vertices[vertex_count++].Y = y_pos;
vertices[vertex_count].X = rect.Left; // Texcoord
vertices[vertex_count++].Y = rect.Top;
vertices[vertex_count].X = x_pos; // Vertex
vertices[vertex_count++].Y = y_pos + char_height;
vertices[vertex_count].X = rect.Left; // Texcoord
vertices[vertex_count++].Y = rect.Bottom;
vertices[vertex_count].X = x_pos + char_width; // Vertex vertices[vertex_count].X = x_pos; // Vertex
vertices[vertex_count++].Y = y_pos + char_height; vertices[vertex_count++].Y = y_pos;
vertices[vertex_count].X = rect.Right; // Texcoord vertices[vertex_count].X = rect.Left; // Texcoord
vertices[vertex_count++].Y = rect.Bottom; vertices[vertex_count++].Y = rect.Top;
vertices[vertex_count].X = x_pos + char_width; // Vertex vertices[vertex_count].X = x_pos; // Vertex
vertices[vertex_count++].Y = y_pos; vertices[vertex_count++].Y = y_pos + char_height;
vertices[vertex_count].X = rect.Right; // Texcoord vertices[vertex_count].X = rect.Left; // Texcoord
vertices[vertex_count++].Y = rect.Top; vertices[vertex_count++].Y = rect.Bottom;
indices[index_count++] = (ushort)(vertex_count - 8); vertices[vertex_count].X = x_pos + char_width; // Vertex
indices[index_count++] = (ushort)(vertex_count - 6); vertices[vertex_count++].Y = y_pos + char_height;
indices[index_count++] = (ushort)(vertex_count - 4); vertices[vertex_count].X = rect.Right; // Texcoord
vertices[vertex_count++].Y = rect.Bottom;
vertices[vertex_count].X = x_pos + char_width; // Vertex
vertices[vertex_count++].Y = y_pos;
vertices[vertex_count].X = rect.Right; // Texcoord
vertices[vertex_count++].Y = rect.Top;
indices[index_count++] = (ushort)(vertex_count - 4); indices[index_count++] = (ushort)(vertex_count - 8);
indices[index_count++] = (ushort)(vertex_count - 2); indices[index_count++] = (ushort)(vertex_count - 6);
indices[index_count++] = (ushort)(vertex_count - 8); indices[index_count++] = (ushort)(vertex_count - 4);
indices[index_count++] = (ushort)(vertex_count - 4);
indices[index_count++] = (ushort)(vertex_count - 2);
indices[index_count++] = (ushort)(vertex_count - 8);
font.MeasureString(text.Substring(i, 1), out measured_width, out measured_height, false);
x_pos += measured_width;
}
else if (c == '\n')
{
//x_pos = layoutRect.Left;
x_pos = 0;
y_pos += font.Height;
}
++i; ++i;
} }
} }
@ -269,7 +272,7 @@ namespace OpenTK.Graphics
/// <param name="handle">The TextHandle to the cached text.</param> /// <param name="handle">The TextHandle to the cached text.</param>
public void Draw(TextHandle handle) public void Draw(TextHandle handle)
{ {
GL.BindTexture(TextureTarget.Texture2D, handle.font.Texture); GL.BindTexture(TextureTarget.Texture2D, handle.Font.Texture);
Printer.Draw(handle); Printer.Draw(handle);
} }

View file

@ -25,7 +25,7 @@ namespace OpenTK.Graphics
public class TextureFont : IFont public class TextureFont : IFont
{ {
Font font; Font font;
Dictionary<char, Box2> loaded_glyphs = new Dictionary<char, Box2>(64); Dictionary<char, RectangleF> loaded_glyphs = new Dictionary<char, RectangleF>(64);
Bitmap bmp; Bitmap bmp;
Graphics gfx; Graphics gfx;
@ -33,15 +33,18 @@ namespace OpenTK.Graphics
static int texture; static int texture;
static TexturePacker<Glyph> pack; static TexturePacker<Glyph> pack;
static int texture_width, texture_height; static int texture_width, texture_height;
static readonly StringFormat default_string_format = StringFormat.GenericTypographic; // Check the constructor, too, for additional flags.
static readonly StringFormat load_glyph_string_format = StringFormat.GenericDefault;
static SizeF maximum_graphics_size;
int[] data = new int[256]; // Used to upload glyph buffer to the OpenGL texture. int[] data = new int[256]; // Used to upload the glyph buffer to the OpenGL texture.
object upload_lock = new object(); object upload_lock = new object();
#region --- Constructor --- #region --- Constructor ---
/// <summary> /// <summary>
/// Constructs a new TextureFont object, using the specified System.Drawing.Font. /// Constructs a new TextureFont, using the specified System.Drawing.Font.
/// </summary> /// </summary>
/// <param name="font">The System.Drawing.Font to use.</param> /// <param name="font">The System.Drawing.Font to use.</param>
public TextureFont(Font font) public TextureFont(Font font)
@ -53,23 +56,337 @@ namespace OpenTK.Graphics
bmp = new Bitmap(font.Height * 2, font.Height * 2); bmp = new Bitmap(font.Height * 2, font.Height * 2);
gfx = Graphics.FromImage(bmp); gfx = Graphics.FromImage(bmp);
maximum_graphics_size = gfx.ClipBounds.Size;
// Adjust font rendering mode. Small sizes look blurry without gridfitting, so turn // Adjust font rendering mode. Small sizes look blurry without gridfitting, so turn
// that on. Increasing contrast also seems to help. // that on. Increasing contrast also seems to help.
if (font.Size <= 18.0f) if (font.Size <= 18.0f)
{ {
gfx.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; gfx.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
gfx.TextContrast = 1; //gfx.TextContrast = 11;
} }
else else
{ {
gfx.TextRenderingHint = TextRenderingHint.AntiAlias; gfx.TextRenderingHint = TextRenderingHint.AntiAlias;
gfx.TextContrast = 0; //gfx.TextContrast = 0;
}
default_string_format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
}
/// <summary>
/// Constructs a new TextureFont, using the specified parameters.
/// </summary>
/// <param name="font">The System.Drawing.FontFamily to use for the typeface.</param>
/// <param name="emSize">The em size to use for the typeface.</param>
public TextureFont(FontFamily family, float emSize)
: this(new Font(family, emSize))
{ }
/// <summary>
/// Constructs a new TextureFont, using the specified parameters.
/// </summary>
/// <param name="font">The System.Drawing.FontFamily to use for the typeface.</param>
/// <param name="emSize">The em size to use for the typeface.</param>
/// <param name="family">The style to use for the typeface.</param>
public TextureFont(FontFamily family, float emSize, FontStyle style)
: this(new Font(family, emSize, style))
{ }
#endregion
#region --- Public Methods ---
#region public void LoadGlyphs(string glyphs)
/// <summary>
/// Prepares the specified glyphs for rendering.
/// </summary>
/// <param name="glyphs">The glyphs to prepare for rendering.</param>
public void LoadGlyphs(string glyphs)
{
RectangleF rect = new RectangleF();
foreach (char c in glyphs)
{
try
{
if (!loaded_glyphs.ContainsKey(c))
LoadGlyph(c, out rect);
}
catch (Exception e)
{
Debug.Print(e.ToString());
throw;
}
} }
} }
#endregion #endregion
#region public void LoadGlyph(char glyph)
/// <summary>
/// Prepares the specified glyph for rendering.
/// </summary>
/// <param name="glyphs">The glyph to prepare for rendering.</param>
public void LoadGlyph(char glyph)
{
RectangleF rect = new RectangleF();
if (!loaded_glyphs.ContainsKey(glyph))
LoadGlyph(glyph, out rect);
}
#endregion
#region public bool GlyphData(char glyph, out float width, out float height, out RectangleF textureRectangle, out int texture)
/// <summary>
/// Returns the characteristics of a loaded glyph.
/// </summary>
/// <param name="glyph">The character corresponding to this glyph.</param>
/// <param name="width">The width of this glyph.</param>
/// <param name="height">The height of this glyph (line spacing).</param>
/// <param name="textureRectangle">The bounding box of the texture buffer of this glyph.</param>
/// <param name="texture">The handle to the texture that contains this glyph.</param>
/// <returns>True if the glyph has been loaded, false otherwise.</returns>
/// <seealso cref="LoadGlyphs"/>
public bool GlyphData(char glyph, out float width, out float height, out RectangleF textureRectangle, out int texture)
{
if (loaded_glyphs.TryGetValue(glyph, out textureRectangle))
{
width = textureRectangle.Width * texture_width;
height = textureRectangle.Height * texture_height;
texture = TextureFont.texture;
return true;
}
width = height = texture = 0;
return false;
}
#endregion
#region public float Height
/// <summary>
/// Gets a float indicating the default line spacing of this font.
/// </summary>
public float Height
{
get { return font.Height; }
}
#endregion
#region public float Width
/// <summary>
/// Gets a float indicating the default size of this font, in points.
/// </summary>
public float Width
{
get { return font.SizeInPoints; }
}
#endregion
#region public void MeasureString(string str, out float width, out float height, bool accountForOverhangs)
/// <summary>
/// Measures the width of the specified string.
/// </summary>
/// <param name="str">The string to measure.</param>
/// <param name="width">The measured width.</param>
/// <param name="height">The measured height.</param>
/// <param name="accountForOverhangs">If true, adds space to account for glyph overhangs. Set to true if you wish to measure a complete string. Set to false if you wish to perform layout on adjacent strings.</param>
[Obsolete("Returns invalid results - use MeasureText() instead")]
public void MeasureString(string str, out float width, out float height, bool accountForOverhangs)
{
System.Drawing.StringFormat format = accountForOverhangs ? System.Drawing.StringFormat.GenericDefault : System.Drawing.StringFormat.GenericTypographic;
//format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
System.Drawing.SizeF size = gfx.MeasureString(str, font, 16384, format);
height = size.Height;
width = size.Width;
//width = height = 0;
//RectangleF rect = new RectangleF(0, 0, 0, 0);
//ICollection<RectangleF> ranges = new List<RectangleF>();
//MeasureCharacterRanges(gfx, str, font, ref rect, format, ref ranges);
//foreach (RectangleF range in ranges)
//{
// width += range.Width;
// height = range.Height > height ?range.Height : height;
//}
// width = 0;
// height = 0;
// int i = 0;
// foreach (char c in str)
// {
// if (c != '\n' && c != '\r')
// {
// SizeF size = gfx.MeasureString(str.Substring(i, 1), font, 16384, System.Drawing.StringFormat.GenericTypographic);
// width += size.Width == 0 ? font.SizeInPoints * 0.5f : size.Width;
// if (height < size.Height)
// height = size.Height;
// }
// ++i;
// }
}
#endregion
#region public void MeasureString(string str, out float width, out float height)
/// <summary>
/// Measures the width of the specified string.
/// </summary>
/// <param name="str">The string to measure.</param>
/// <param name="width">The measured width.</param>
/// <param name="height">The measured height.</param>
/// <seealso cref="public void MeasureString(string str, out float width, out float height, bool accountForOverhangs)"/>
[Obsolete("Returns invalid results - use MeasureText() instead")]
public void MeasureString(string str, out float width, out float height)
{
MeasureString(str, out width, out height, true);
}
#endregion
#region public RectangleF MeasureText(string text)
/// <summary>
/// Calculates size information for the specified text.
/// </summary>
/// <param name="text">The string to measure.</param>
/// <returns>A RectangleF containing the bounding box for the specified text.</returns>
public RectangleF MeasureText(string text)
{
return MeasureText(text, SizeF.Empty, default_string_format, null);
}
#endregion
#region public RectangleF MeasureText(string text, SizeF bounds)
/// <summary>
/// Calculates size information for the specified text.
/// </summary>
/// <param name="text">The string to measure.</param>
/// <param name="bounds">A SizeF structure containing the maximum desired width and height of the text. Default is SizeF.Empty.</param>
/// <returns>A RectangleF containing the bounding box for the specified text.</returns>
public RectangleF MeasureText(string text, SizeF bounds)
{
return MeasureText(text, bounds, default_string_format, null);
}
#endregion
#region public RectangleF MeasureText(string text, SizeF bounds, StringFormat format)
/// <summary>
/// Calculates size information for the specified text.
/// </summary>
/// <param name="text">The string to measure.</param>
/// <param name="bounds">A SizeF structure containing the maximum desired width and height of the text. Pass SizeF.Empty to disable wrapping calculations. A width or height of 0 disables the relevant calculation.</param>
/// <param name="format">A StringFormat object which specifies the measurement format of the string. Pass null to use the default StringFormat (StringFormat.GenericTypographic).</param>
/// <returns>A RectangleF containing the bounding box for the specified text.</returns>
public RectangleF MeasureText(string text, SizeF bounds, StringFormat format)
{
return MeasureText(text, bounds, format, null);
}
#endregion
#region public RectangleF MeasureText(string text, SizeF bounds, StringFormat format, IList<RectangleF> ranges)
/// <summary>
/// Calculates size information for the specified text.
/// </summary>
/// <param name="text">The string to measure.</param>
/// <param name="bounds">A SizeF structure containing the maximum desired width and height of the text. Pass SizeF.Empty to disable wrapping calculations. A width or height of 0 disables the relevant calculation.</param>
/// <param name="format">A StringFormat object which specifies the measurement format of the string. Pass null to use the default StringFormat (StringFormat.GenericDefault).</param>
/// <param name="ranges">Fills the specified IList of RectangleF structures with position information for individual characters. If this argument is null, these calculations are skipped.</param>
/// <returns>A RectangleF containing the bounding box for the specified text.</returns>
public RectangleF MeasureText(string text, SizeF bounds, StringFormat format, IList<RectangleF> ranges)
{
int status = 0;
if (String.IsNullOrEmpty(text))
return RectangleF.Empty;
if (bounds == SizeF.Empty)
bounds = maximum_graphics_size;
if (format == null)
format = default_string_format;
if (ranges != null)
ranges.Clear();
IntPtr[] regions = new IntPtr[GdiPlus.MaxMeasurableCharacterRanges];
CharacterRange[] characterRanges = new CharacterRange[GdiPlus.MaxMeasurableCharacterRanges];
PointF origin = PointF.Empty;
SizeF size = SizeF.Empty;
RectangleF rect = new RectangleF();
for (int i = 0; i < text.Length; i += GdiPlus.MaxMeasurableCharacterRanges)
{
int num_characters = text.Length - i > GdiPlus.MaxMeasurableCharacterRanges ? GdiPlus.MaxMeasurableCharacterRanges : text.Length - i;
for (int j = 0; j < num_characters; j++)
{
characterRanges[j] = new CharacterRange(i + j, 1);
IntPtr region;
status = GdiPlus.CreateRegion(out region);
regions[j] = region;
if (status != 0)
Debug.Print("GDI+ error: {0}", status);
}
CharacterRange[] a = (CharacterRange[])characterRanges.Clone();
Array.Resize(ref a, num_characters);
format.SetMeasurableCharacterRanges(a);
IntPtr native_graphics = GdiPlus.GetNativeGraphics(gfx);
IntPtr native_font = GdiPlus.GetNativeFont(font);
IntPtr native_string_format = GdiPlus.GetNativeStringFormat(format);
RectangleF layoutRect = new RectangleF(PointF.Empty, bounds);
status = GdiPlus.MeasureCharacterRanges(new HandleRef(gfx, native_graphics), text, text.Length,
new HandleRef(font, native_font), ref layoutRect,
new HandleRef(format, (format == null) ? IntPtr.Zero : native_string_format),
num_characters, regions);
for (int j = 0; j < num_characters; j++)
{
status = GdiPlus.GetRegionBounds(regions[j], new HandleRef(gfx, GdiPlus.GetNativeGraphics(gfx)), ref rect);
if (i == 0 && j == 0)
origin = rect.Location;
//if (origin.X > 0)
// rect.X -= (float)System.Math.Floor(origin.X);
if (ranges != null)
ranges.Add(rect);
status = GdiPlus.DeleteRegion(regions[j]);
}
}
//origin.X = 0;
return new RectangleF(origin.X, origin.Y, rect.Right, rect.Bottom);
}
#endregion
#endregion
#region --- Private Methods ---
#region private void PrepareTexturePacker() #region private void PrepareTexturePacker()
/// <summary> /// <summary>
@ -101,53 +418,18 @@ namespace OpenTK.Graphics
#endregion #endregion
#region public void LoadGlyphs(string glyphs) #region private void LoadGlyph(char c, out RectangleF rectangle)
/// <summary> // Adds the specified caharacter to the texture packer.
/// Prepares the specified glyphs for rendering. private void LoadGlyph(char c, out RectangleF rectangle)
/// </summary>
/// <param name="glyphs">The glyphs to prepare for rendering.</param>
public void LoadGlyphs(string glyphs)
{
Box2 rect = new Box2();
foreach (char c in glyphs)
{
if (!loaded_glyphs.ContainsKey(c))
LoadGlyph(c, out rect);
}
}
#endregion
#region public void LoadGlyph(char glyph)
/// <summary>
/// Prepares the specified glyph for rendering.
/// </summary>
/// <param name="glyphs">The glyph to prepare for rendering.</param>
public void LoadGlyph(char glyph)
{
Box2 rect = new Box2();
if (!loaded_glyphs.ContainsKey(glyph))
LoadGlyph(glyph, out rect);
}
#endregion
#region private void LoadGlyph(char c, out Box2 rectangle)
/// <summary>
/// Adds a glyph to the texture packer.
/// </summary>
/// <param name="c">The character of the glyph.</param>
/// <param name="rectangle">An OpenTK.Math.Box2 that will hold the buffer for this glyph.</param>
private void LoadGlyph(char c, out Box2 rectangle)
{ {
if (pack == null) if (pack == null)
PrepareTexturePacker(); PrepareTexturePacker();
Glyph g = new Glyph(c, font); RectangleF glyph_rect = MeasureText(c.ToString(), SizeF.Empty, load_glyph_string_format);
Rectangle rect = new Rectangle(); SizeF glyph_size = new SizeF(glyph_rect.Right, glyph_rect.Bottom); // We need to do this, since the origin might not be (0, 0)
Glyph g = new Glyph(c, font, glyph_size);
Rectangle rect;
try try
{ {
@ -162,8 +444,9 @@ namespace OpenTK.Graphics
GL.BindTexture(TextureTarget.Texture2D, texture); GL.BindTexture(TextureTarget.Texture2D, texture);
//gfx.TextRenderingHint = TextRenderingHint.AntiAlias;
gfx.Clear(System.Drawing.Color.Transparent); gfx.Clear(System.Drawing.Color.Transparent);
gfx.DrawString(g.Character.ToString(), g.Font, System.Drawing.Brushes.White, 0.0f, 0.0f); gfx.DrawString(g.Character.ToString(), g.Font, System.Drawing.Brushes.White, 0.0f, 0.0f, default_string_format);
//BitmapData bitmap_data = bitmap.LockBits(new Rectangle(0, 0, rect.Width, rect.Height), ImageLockMode.ReadOnly, //BitmapData bitmap_data = bitmap.LockBits(new Rectangle(0, 0, rect.Width, rect.Height), ImageLockMode.ReadOnly,
// System.Drawing.Imaging.PixelFormat.Format32bppArgb); // System.Drawing.Imaging.PixelFormat.Format32bppArgb);
@ -181,12 +464,8 @@ namespace OpenTK.Graphics
{ {
int* bitmap_data_ptr = (int*)bitmap_data.Scan0; int* bitmap_data_ptr = (int*)bitmap_data.Scan0;
for (int y = 0; y < rect.Height; y++) for (int y = 0; y < rect.Height; y++)
{
for (int x = 0; x < rect.Width; x++) for (int x = 0; x < rect.Width; x++)
{
data[y * rect.Width + x] = *(bitmap_data_ptr + y * bmp.Width + x); data[y * rect.Width + x] = *(bitmap_data_ptr + y * bmp.Width + x);
}
}
fixed (int* data_ptr = data) fixed (int* data_ptr = data)
GL.TexSubImage2D(TextureTarget.Texture2D, 0, rect.Left, rect.Top, rect.Width, rect.Height, GL.TexSubImage2D(TextureTarget.Texture2D, 0, rect.Left, rect.Top, rect.Width, rect.Height,
@ -194,7 +473,7 @@ namespace OpenTK.Graphics
} }
bmp.UnlockBits(bitmap_data); bmp.UnlockBits(bitmap_data);
rectangle = new Box2( rectangle = RectangleF.FromLTRB(
rect.Left / (float)texture_width, rect.Left / (float)texture_width,
rect.Top / (float)texture_height, rect.Top / (float)texture_height,
rect.Right / (float)texture_width, rect.Right / (float)texture_width,
@ -206,56 +485,9 @@ namespace OpenTK.Graphics
#endregion #endregion
#region public bool GlyphData(char glyph, out float width, out float height, out Box2 textureRectangle, out int texture)
/// <summary>
/// Returns the characteristics of a loaded glyph.
/// </summary>
/// <param name="glyph">The character corresponding to this glyph.</param>
/// <param name="width">The width of this glyph.</param>
/// <param name="height">The height of this glyph (line spacing).</param>
/// <param name="textureRectangle">The bounding box of the texture buffer of this glyph.</param>
/// <param name="texture">The handle to the texture that contains this glyph.</param>
/// <returns>True if the glyph has been loaded, false otherwise.</returns>
/// <seealso cref="LoadGlyphs"/>
public bool GlyphData(char glyph, out float width, out float height, out Box2 textureRectangle, out int texture)
{
if (loaded_glyphs.TryGetValue(glyph, out textureRectangle))
{
width = textureRectangle.Width * texture_width;
height = textureRectangle.Height * texture_height;
texture = TextureFont.texture;
return true;
}
width = height = texture = 0;
return false;
}
#endregion #endregion
#region public float Height #region --- Internal Methods ---
/// <summary>
/// Gets a float indicating the default line spacing of this font.
/// </summary>
public float Height
{
get { return font.Height; }
}
#endregion
#region public float Width
/// <summary>
/// Gets a float indicating the default line spacing of this font.
/// </summary>
public float Width
{
get { return font.SizeInPoints; }
}
#endregion
#region internal int Texture #region internal int Texture
@ -269,56 +501,6 @@ namespace OpenTK.Graphics
#endregion #endregion
#region public void MeasureString(string str, out float width, out float height, bool accountForOverhangs)
/// <summary>
/// Measures the width of the specified string.
/// </summary>
/// <param name="str">The string to measure.</param>
/// <param name="width">The measured width.</param>
/// <param name="height">The measured height.</param>
/// <param name="addSpace">If true, adds space to account for glyph overhangs. Set to true if you wish to measure a complete string. Set to false if you wish to perform layout on adjacent strings.</param>
public void MeasureString(string str, out float width, out float height, bool accountForOverhangs)
{
System.Drawing.StringFormat format = accountForOverhangs ? System.Drawing.StringFormat.GenericDefault : System.Drawing.StringFormat.GenericTypographic;
format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
System.Drawing.SizeF size = gfx.MeasureString(str, font, 16384, format);
height = size.Height;
width = size.Width;
// width = 0;
// height = 0;
// int i = 0;
// foreach (char c in str)
// {
// if (c != '\n' && c != '\r')
// {
// SizeF size = gfx.MeasureString(str.Substring(i, 1), font, 16384, System.Drawing.StringFormat.GenericTypographic);
// width += size.Width == 0 ? font.SizeInPoints * 0.5f : size.Width;
// if (height < size.Height)
// height = size.Height;
// }
// ++i;
// }
}
#endregion
#region public void MeasureString(string str, out float width, out float height)
/// <summary>
/// Measures the width of the specified string.
/// </summary>
/// <param name="str">The string to measure.</param>
/// <param name="width">The measured width.</param>
/// <param name="height">The measured height.</param>
/// <seealso cref="public void MeasureString(string str, out float width, out float height, bool accountForOverhangs)"/>
public void MeasureString(string str, out float width, out float height)
{
MeasureString(str, out width, out height, true);
}
#endregion #endregion
#region --- IDisposable Members --- #region --- IDisposable Members ---

View file

@ -31,6 +31,8 @@ namespace OpenTK
#endregion #endregion
#region --- Public Methods ---
#region public Rectangle Add(T item) #region public Rectangle Add(T item)
/// <summary> /// <summary>
@ -91,6 +93,8 @@ namespace OpenTK
#endregion #endregion
#endregion
#region Node #region Node
class Node class Node