<Compile Include="src\SelectionChangeEventArgs.cs" />\r
<Compile Include="src\ValueChangeEventArgs.cs" />\r
<Compile Include="src\GraphicObjects\FileDialog.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\ClipShader.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Context.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Path.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Shader %28copier%29.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Surface.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Font\Font.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Font\FontExtents.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Font\FontFace.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Font\FontFlag.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Font\FontShader.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Font\FontSlant.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Font\FontWeight.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Font\glFont.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Font\glGlyph.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Font\TextExtents.cs" />\r
+ <Compile Include="src\OpenGL\GLBackend\Font\FontStyle.cs" />\r
</ItemGroup>\r
<ItemGroup>\r
<Reference Include="System" />\r
<Folder Include="Images\Icons\" />\r
<Folder Include="src\CompilerServices\" />\r
<Folder Include="src\OpenGL\" />\r
+ <Folder Include="src\OpenGL\GLBackend\" />\r
+ <Folder Include="src\OpenGL\GLBackend\Font\" />\r
</ItemGroup>\r
<ItemGroup>\r
<EmbeddedResource Include="Images\Icons\updown.svg" />\r
<None Include="Images\Icons\Cursors\move" />\r
<None Include="README.md" />\r
</ItemGroup>\r
+ <ItemGroup>\r
+ <ProjectReference Include="..\SharpFont-2.5.0.1\SharpFont\SharpFont.csproj">\r
+ <Project>{C293DB32-FA42-486D-B128-5A12522FAE4E}</Project>\r
+ <Name>SharpFont</Name>\r
+ </ProjectReference>\r
+ </ItemGroup>\r
</Project>\r
EndProject\r
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDevelop.Diagram", "..\MonoDevelop.Diagram\MonoDevelop.Diagram.csproj", "{232716B4-D19D-4FD7-B310-94A98FD926F0}"\r
EndProject\r
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpFont", "..\SharpFont-2.5.0.1\SharpFont\SharpFont.csproj", "{C293DB32-FA42-486D-B128-5A12522FAE4E}"\r
+EndProject\r
Global\r
GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
Debug|Linux_x86 = Debug|Linux_x86\r
Release|Linux_x86 = Release|Linux_x86\r
+ Debug WIN64|Any CPU = Debug WIN64|Any CPU\r
+ Release WIN64|Any CPU = Release WIN64|Any CPU\r
EndGlobalSection\r
GlobalSection(ProjectConfigurationPlatforms) = postSolution\r
+ {232716B4-D19D-4FD7-B310-94A98FD926F0}.Debug WIN64|Any CPU.ActiveCfg = Debug|Any CPU\r
+ {232716B4-D19D-4FD7-B310-94A98FD926F0}.Debug WIN64|Any CPU.Build.0 = Debug|Any CPU\r
{232716B4-D19D-4FD7-B310-94A98FD926F0}.Debug|Linux_x86.ActiveCfg = Debug|Any CPU\r
+ {232716B4-D19D-4FD7-B310-94A98FD926F0}.Release WIN64|Any CPU.ActiveCfg = Debug|Any CPU\r
+ {232716B4-D19D-4FD7-B310-94A98FD926F0}.Release WIN64|Any CPU.Build.0 = Debug|Any CPU\r
{232716B4-D19D-4FD7-B310-94A98FD926F0}.Release|Linux_x86.ActiveCfg = Debug|Any CPU\r
+ {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Debug WIN64|Any CPU.ActiveCfg = Debug|Any CPU\r
+ {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Debug WIN64|Any CPU.Build.0 = Debug|Any CPU\r
{74289092-9F70-4941-AFCB-DFD7BE2140B6}.Debug|Linux_x86.ActiveCfg = Debug|Any CPU\r
{74289092-9F70-4941-AFCB-DFD7BE2140B6}.Debug|Linux_x86.Build.0 = Debug|Any CPU\r
+ {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release WIN64|Any CPU.ActiveCfg = Debug|Any CPU\r
+ {74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release WIN64|Any CPU.Build.0 = Debug|Any CPU\r
{74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release|Linux_x86.ActiveCfg = Release|Any CPU\r
{74289092-9F70-4941-AFCB-DFD7BE2140B6}.Release|Linux_x86.Build.0 = Release|Any CPU\r
+ {C293DB32-FA42-486D-B128-5A12522FAE4E}.Debug WIN64|Any CPU.ActiveCfg = Debug WIN64|Any CPU\r
+ {C293DB32-FA42-486D-B128-5A12522FAE4E}.Debug WIN64|Any CPU.Build.0 = Debug WIN64|Any CPU\r
+ {C293DB32-FA42-486D-B128-5A12522FAE4E}.Debug|Linux_x86.ActiveCfg = Debug|Any CPU\r
+ {C293DB32-FA42-486D-B128-5A12522FAE4E}.Debug|Linux_x86.Build.0 = Debug|Any CPU\r
+ {C293DB32-FA42-486D-B128-5A12522FAE4E}.Release WIN64|Any CPU.ActiveCfg = Release WIN64|Any CPU\r
+ {C293DB32-FA42-486D-B128-5A12522FAE4E}.Release WIN64|Any CPU.Build.0 = Release WIN64|Any CPU\r
+ {C293DB32-FA42-486D-B128-5A12522FAE4E}.Release|Linux_x86.ActiveCfg = Release|Any CPU\r
+ {C293DB32-FA42-486D-B128-5A12522FAE4E}.Release|Linux_x86.Build.0 = Release|Any CPU\r
+ {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Debug WIN64|Any CPU.ActiveCfg = Release|Any CPU\r
+ {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Debug WIN64|Any CPU.Build.0 = Release|Any CPU\r
{C2980F9B-4798-4C05-99E2-E174810F7C7B}.Debug|Linux_x86.ActiveCfg = Debug|Any CPU\r
{C2980F9B-4798-4C05-99E2-E174810F7C7B}.Debug|Linux_x86.Build.0 = Debug|Any CPU\r
+ {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Release WIN64|Any CPU.ActiveCfg = Release|Any CPU\r
+ {C2980F9B-4798-4C05-99E2-E174810F7C7B}.Release WIN64|Any CPU.Build.0 = Release|Any CPU\r
{C2980F9B-4798-4C05-99E2-E174810F7C7B}.Release|Linux_x86.ActiveCfg = Release|Any CPU\r
{C2980F9B-4798-4C05-99E2-E174810F7C7B}.Release|Linux_x86.Build.0 = Release|Any CPU\r
+ {E9E14DB5-3C67-4E01-B5C3-4D90D7E31A2E}.Debug WIN64|Any CPU.ActiveCfg = Debug|Any CPU\r
+ {E9E14DB5-3C67-4E01-B5C3-4D90D7E31A2E}.Debug WIN64|Any CPU.Build.0 = Debug|Any CPU\r
{E9E14DB5-3C67-4E01-B5C3-4D90D7E31A2E}.Debug|Linux_x86.ActiveCfg = Debug|Any CPU\r
{E9E14DB5-3C67-4E01-B5C3-4D90D7E31A2E}.Debug|Linux_x86.Build.0 = Debug|Any CPU\r
+ {E9E14DB5-3C67-4E01-B5C3-4D90D7E31A2E}.Release WIN64|Any CPU.ActiveCfg = Debug|Any CPU\r
+ {E9E14DB5-3C67-4E01-B5C3-4D90D7E31A2E}.Release WIN64|Any CPU.Build.0 = Debug|Any CPU\r
{E9E14DB5-3C67-4E01-B5C3-4D90D7E31A2E}.Release|Linux_x86.ActiveCfg = Release|Any CPU\r
EndGlobalSection\r
GlobalSection(MonoDevelopProperties) = preSolution\r
<OutputType>Exe</OutputType>
<RootNamespace>Tests</RootNamespace>
<AssemblyName>Tests</AssemblyName>
- <StartupObject>test2.GOLIBTest_DirViewer</StartupObject>
+ <StartupObject>testGLBackend.GOLIBTestglb</StartupObject>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<OutputPath>..\bin\$(configuration)</OutputPath>
<IntermediateOutputPath>obj\$(configuration)</IntermediateOutputPath>
<HintPath>..\..\opentk\Binaries\OpenTK\Release\OpenTK.dll</HintPath>
</Reference>
<Reference Include="Mono.Cairo" />
+ <Reference Include="GGL">
+ <HintPath>..\..\GGL\bin\GGL.dll</HintPath>
+ </Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="GOLIBTest_5.cs" />
<Compile Include="..\bin\Debug\Interfaces\test4.goml.cs">
<Link>Interfaces\test4.goml.cs</Link>
</Compile>
+ <Compile Include="testGLBackend.cs" />
+ <Compile Include="testGLBackend %28copier%29.cs" />
</ItemGroup>
<ItemGroup>
<None Include="image\u.svg">
<Project>{C2980F9B-4798-4C05-99E2-E174810F7C7B}</Project>
<Name>GOLib</Name>
</ProjectReference>
+ <ProjectReference Include="..\..\SharpFont-2.5.0.1\SharpFont\SharpFont.csproj">
+ <Project>{C293DB32-FA42-486D-B128-5A12522FAE4E}</Project>
+ <Name>SharpFont</Name>
+ </ProjectReference>
</ItemGroup>
</Project>
--- /dev/null
+#define MONO_CAIRO_DEBUG_DISPOSE
+
+
+using System;
+using System.Runtime.InteropServices;
+using OpenTK;
+using OpenTK.Graphics.OpenGL;
+using OpenTK.Input;
+
+using System.Diagnostics;
+
+using go;
+using System.Threading;
+using GGL;
+//using Cairo;
+using go.GLBackend;
+
+namespace testGLBackend2
+{
+ class GOLIBTestglb : OpenTKGameWindow
+ {
+ #region FPS
+ static int _fps = 0;
+
+ public static int fps {
+ get { return _fps; }
+ set {
+ _fps = value;
+ if (_fps > fpsMax)
+ fpsMax = _fps;
+ else if (_fps < fpsMin)
+ fpsMin = _fps;
+ }
+
+ }
+
+ public static int fpsMin = int.MaxValue;
+ public static int fpsMax = 0;
+
+ static void resetFps ()
+ {
+ fpsMin = int.MaxValue;
+ fpsMax = 0;
+ _fps = 0;
+ }
+ #endregion
+
+ public GOLIBTestglb ()
+ : base(1024, 800)
+ {
+ VSync = VSyncMode.Off;
+ }
+
+ #region scene matrix and vectors
+ public static Matrix4 modelview;
+ public static Matrix4 projection;
+
+ public static Vector3 vEye = new Vector3(5.0f, 5.0f, 5.0f); // Camera Position
+ public static Vector3 vEyeTarget = Vector3.Zero;
+ public static Vector3 vLook = new Vector3(0f, 1f, -0.7f); // Camera vLook Vector
+
+ float _zFar = 6400.0f;
+
+ public float zFar {
+ get { return _zFar; }
+ set {
+ _zFar = value;
+ }
+ }
+
+ public float zNear = 0.1f;
+ public float fovY = (float)Math.PI / 4;
+
+ float MoveSpeed = 0.5f;
+ float RotationSpeed = 0.02f;
+ #endregion
+
+ Context ctx;
+ Surface surf;
+
+ QuadVAO testQuad;
+ go.GLBackend.Shader shad;
+ Matrix4 projectionMatrix,
+ modelviewMatrix;
+ Texture testTex;
+
+ void drawScene()
+ {
+ //shad.Enable ();
+ //shader.LineWidth = lineWidth;
+ shad.ProjectionMatrix = projectionMatrix;
+ shad.ModelViewMatrix = modelviewMatrix;
+ shad.Color = new Vector4(1f,1f,1f,1f);
+
+ GL.ActiveTexture (TextureUnit.Texture0);
+ GL.BindTexture(TextureTarget.Texture2D, surf.texId);
+
+ testQuad.Render (PrimitiveType.TriangleStrip);
+
+ GL.BindTexture(TextureTarget.Texture2D, 0);
+
+ //shad.Disable ();
+ }
+
+ protected override void OnLoad (EventArgs e)
+ {
+ base.OnLoad (e);
+
+
+ Mouse.WheelChanged += new EventHandler<MouseWheelEventArgs>(Mouse_WheelChanged);
+ Mouse.Move += new EventHandler<MouseMoveEventArgs>(Mouse_Move);
+
+ GL.Viewport (0, 0, ClientRectangle.Width, ClientRectangle.Height);
+ GL.ClearColor(0.0f, 0.0f, 0.2f, 1.0f);
+
+// GL.Enable(EnableCap.DepthTest);
+// GL.DepthFunc(DepthFunction.Less);
+ //GL.Enable(EnableCap.CullFace);
+ //GL.Enable(EnableCap.Texture2D);
+
+ GL.Enable (EnableCap.Blend);
+ GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
+
+ //GL.FrontFace(FrontFaceDirection.Ccw);
+
+ //GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
+ //GL.ShadeModel(ShadingModel.Smooth);
+ //GL.Hint (HintTarget.LineSmoothHint, HintMode.Nicest);
+ ErrorCode err = GL.GetError ();
+ Debug.Assert (err == ErrorCode.NoError, "OpenGL Error");
+
+ surf = new Surface (Format.Argb32, 600, 600);
+
+ testQuad = new QuadVAO (100, 100, 600, 600);
+ shad = new TexturedShader ();
+
+ projectionMatrix = Matrix4.CreateOrthographicOffCenter
+ (0, ClientRectangle.Width, ClientRectangle.Height, 0, 0, 1);
+ modelviewMatrix = Matrix4.Identity;
+
+ testTex = new Texture (rootDir + @"Images/texture/structures/639-diffuse.jpg");
+ //string[] extensions = GL.GetString(StringName.Version).Split(' ');
+ LoadInterface("Interfaces/test0.goml");
+
+ }
+ public static void DrawRoundedRectangle(Context gr, double x, double y, double width, double height, double radius)
+ {
+
+ if ((radius > height / 2) || (radius > width / 2))
+ radius = Math.Min(height / 2, width / 2);
+
+ gr.MoveTo(x, y + radius);
+ gr.Arc(x + radius, y + radius, radius, Math.PI, -Math.PI / 2);
+ gr.LineTo(x + width - radius, y);
+ gr.Arc(x + width - radius, y + radius, radius, -Math.PI / 2, 0);
+ gr.LineTo(x + width, y + height - radius);
+ gr.Arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2);
+ gr.LineTo(x + radius, y + height);
+ gr.Arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI);
+ gr.ClosePath();
+ }
+ double angle;
+ public override void GLClear ()
+ {
+ GL.ClearColor(0.0f, 0.0f, 0.2f, 1.0f);
+ GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
+ }
+ public override void OnRender (FrameEventArgs e)
+ {
+ drawScene ();
+ }
+
+ protected override void OnUpdateFrame (FrameEventArgs e)
+ {
+ base.OnUpdateFrame (e);
+
+ fps = (int)RenderFrequency;
+
+ using (Context ctx = new Context (surf)) {
+ ctx.LineWidth = 1.0;
+ ctx.Rectangle (new Rectangle (0, 0, 600, 600));
+ DrawRoundedRectangle (ctx, 100, 100, 70, 70, 10);
+ ctx.Color = go.Color.Green;
+ ctx.FillPreserve ();
+
+ for (int i = 0; i < 5; i++) {
+
+
+ angle += Math.PI / 1000;
+ if (angle > Math.PI * 2)
+ angle = 0;
+
+ ctx.Translate (-200, -200);
+ ctx.Rotate (angle);
+ ctx.Translate (200, 200);
+
+ //ctx.FillPreserve ();
+ ctx.Color = go.Color.White;
+ //ctx.Color.AdjustAlpha (1.0 / i);
+ ctx.StrokePreserve ();
+ }
+ }
+ //surf.Save (@"/home/jp/test.png");
+ //Debug.WriteLine (fps);
+ this.Title = fps.ToString ();
+ }
+ protected override void OnResize (EventArgs e)
+ {
+ base.OnResize (e);
+ UpdateViewMatrix();
+ }
+
+ #region Mouse Handling
+ void Object_Mouse_Move(object sender, MouseMoveEventArgs e){
+ if (activeWidget == null)
+ return;
+
+ activeWidget.registerClipRect ();
+ if (activeWidget!=null) {
+ activeWidget.Left += e.XDelta;
+ activeWidget.Top += e.YDelta;
+ }
+ }
+ void Mouse_Move(object sender, MouseMoveEventArgs e)
+ {
+ if (e.XDelta != 0 || e.YDelta != 0)
+ {
+ if (e.Mouse.MiddleButton == OpenTK.Input.ButtonState.Pressed)
+ {
+ Matrix4 m = Matrix4.CreateRotationZ(-e.XDelta * RotationSpeed);
+ m *= Matrix4.CreateFromAxisAngle(-vLookPerpendicularOnXYPlane, -e.YDelta * RotationSpeed);
+ vEyeTarget = Vector3.Zero;
+ vEye = Vector3.Transform(vEye, Matrix4.CreateTranslation(-vEyeTarget) * m * Matrix4.CreateTranslation(vEyeTarget));
+ UpdateViewMatrix();
+ }
+ if (e.Mouse.RightButton == ButtonState.Pressed)
+ {
+
+ Matrix4 m = Matrix4.CreateRotationZ(-e.XDelta * RotationSpeed);
+ Matrix4 m2 = Matrix4.Rotate(vLookPerpendicularOnXYPlane, e.YDelta * RotationSpeed);
+
+ vEyeTarget = Vector3.Transform(vEyeTarget, Matrix4.CreateTranslation(-vEye) * m * m2 * Matrix4.CreateTranslation(vEye));
+
+ //vLook = Vector3.Transform(vLook, m2);
+ UpdateViewMatrix();
+
+ }
+ }
+ }
+ void Mouse_WheelChanged(object sender, MouseWheelEventArgs e)
+ {
+ float speed = MoveSpeed;
+ if (Keyboard[Key.ShiftLeft])
+ speed *= 0.1f;
+ else if (Keyboard[Key.ControlLeft])
+ speed *= 20.0f;
+
+ vLook = Vector3.NormalizeFast(vEye - vEyeTarget);
+ vEye -= vLook * e.Delta * speed;
+ UpdateViewMatrix();
+ }
+ #endregion
+
+ #region vLookCalculations
+ Vector3 vLookDirOnXYPlane
+ {
+ get
+ {
+ Vector3 v = Vector3.NormalizeFast(vEye - vEyeTarget);
+ v.Z = 0;
+ return v;
+ }
+ }
+ public Vector3 vLookPerpendicularOnXYPlane
+ {
+ get
+ {
+ Vector3 vLook = Vector3.NormalizeFast(vEye - vEyeTarget);
+ vLook.Z = 0;
+
+ Vector3 vHorizDir = Vector3.Cross(vLook, Vector3.UnitZ);
+ return vHorizDir;
+ }
+ }
+
+ void moveCamera(Vector3 v)
+ {
+ vEye += v;
+ vEyeTarget += v;
+ }
+ #endregion
+
+ public void UpdateViewMatrix()
+ {
+// Rectangle r = this.ClientRectangle;
+// GL.Viewport( r.X, r.Y, r.Width, r.Height);
+// projection = Matrix4.CreatePerspectiveFieldOfView(fovY, r.Width / (float)r.Height, zNear, zFar);
+// GL.MatrixMode(MatrixMode.Projection);
+// GL.LoadIdentity();
+//
+// GL.LoadMatrix(ref projection);
+//
+// modelview = Matrix4.LookAt(vEye, vEyeTarget, Vector3.UnitZ);
+// GL.MatrixMode(MatrixMode.Modelview);
+// GL.LoadIdentity();
+// GL.LoadMatrix(ref modelview);
+ }
+ [STAThread]
+ static void Main ()
+ {
+ Console.WriteLine ("starting example");
+
+ using (GOLIBTestglb win = new GOLIBTestglb( )) {
+ win.Run (30.0);
+ }
+ }
+ }
+}
+//using (Context ctx = new Context (surf)) {
+// //for (int i = 0; i < 150; i++) {
+//
+//
+// // angle += Math.PI / 100000;
+// // if (angle > Math.PI * 2)
+// // angle = 0;
+// //GL.
+// //drawScene();
+//
+// // ctx.Color = new Color (1.0/i, 1, 0, 1);
+// // ctx.Translate (-512, -400);
+// // ctx.Rotate (angle);
+// // ctx.Translate (512, 400);
+// ctx.LineWidth = 1.0;
+// ctx.Color = go.Color.LightBlue.AdjustAlpha(0.2);
+// // ctx.MoveTo (100, 100);
+// // ctx.LineTo (150, 150);
+// // ctx.LineTo (300, 100);
+// // ctx.LineTo (150, 200);
+// // ctx.LineTo (500, 200);
+// // ctx.LineTo (400, 100);
+// // ctx.LineTo (600, 100);
+// // ctx.LineTo (600, 600);
+// // ctx.LineTo (200, 600);
+// // ctx.LineTo (300, 300);
+// // ctx.LineTo (100, 300);
+// // //ctx.ClosePath ();
+// //ctx.Rectangle(new go.Rectangle(100,600,60,80));
+//
+// DrawRoundedRectangle (ctx, 200, 200, 70, 70,10);
+// // DrawRoundedRectangle (ctx, 300, 300, 70, 70,5);
+// // DrawRoundedRectangle (ctx, 400, 400, 70, 70,25);
+// // DrawRoundedRectangle (ctx, 500, 500, 70, 70,25);
+// // DrawRoundedRectangle (ctx, 600, 600, 100, 100,25);
+//
+//
+// //**** concave shape
+//
+// // ctx.LineTo (110, 200);
+// // ctx.LineTo (400, 200);
+// // ctx.LineTo (400, 100);
+// // ctx.LineTo (200, 100);
+// // ctx.LineTo (200, 50);
+// // ctx.LineTo (500, 50);
+// // ctx.LineTo (500, 200);
+// // ctx.LineTo (400, 300);
+// // ctx.LineTo (100, 300);
+// // ctx.LineTo (50, 200);
+// ctx.FillPreserve ();
+// //*****************************
+//
+// ctx.Color = go.Color.White;
+// //ctx.Stroke ();
+// // ctx.LineTo (500, 50);
+// // ctx.LineTo (750, 500);
+// // ctx.LineTo (750, 50);
+// // ctx.MoveTo (100, 100);
+// // ctx.LineTo (200, 200);
+// // ctx.LineTo (100, 400);
+// // ctx.LineTo (300, 400);
+// // //ctx.LineTo (250, 300);
+// // ctx.Arc (300, 600, 100, 0, Math.PI);
+// ctx.Stroke ();
+//}
+////}
--- /dev/null
+#define MONO_CAIRO_DEBUG_DISPOSE
+
+
+using System;
+using System.Runtime.InteropServices;
+using OpenTK;
+using OpenTK.Graphics.OpenGL;
+using OpenTK.Input;
+
+using System.Diagnostics;
+
+using go;
+using System.Threading;
+using GGL;
+//using Cairo;
+using go.GLBackend;
+
+namespace testGLBackend
+{
+ class GOLIBTestglb : OpenTKGameWindow
+ {
+ #region FPS
+ static int _fps = 0;
+
+ public static int fps {
+ get { return _fps; }
+ set {
+ _fps = value;
+ if (_fps > fpsMax)
+ fpsMax = _fps;
+ else if (_fps < fpsMin)
+ fpsMin = _fps;
+ }
+
+ }
+
+ public static int fpsMin = int.MaxValue;
+ public static int fpsMax = 0;
+
+ static void resetFps ()
+ {
+ fpsMin = int.MaxValue;
+ fpsMax = 0;
+ _fps = 0;
+ }
+ #endregion
+
+ public float coef1 = 1.0f;
+ public float coef2 = 0.5f;
+ public float coef3 = 0.0f;
+ public float coefA = 1.0f;
+
+ Color foreground = Color.Black;
+ Color background = Color.White;
+
+ public GOLIBTestglb ()
+ : base(1024, 800)
+ {
+ VSync = VSyncMode.Off;
+ }
+
+ #region scene matrix and vectors
+ public static Matrix4 modelview;
+ public static Matrix4 projection;
+
+ public static Vector3 vEye = new Vector3(5.0f, 5.0f, 5.0f); // Camera Position
+ public static Vector3 vEyeTarget = Vector3.Zero;
+ public static Vector3 vLook = new Vector3(0f, 1f, -0.7f); // Camera vLook Vector
+
+ float _zFar = 6400.0f;
+
+ public float zFar {
+ get { return _zFar; }
+ set {
+ _zFar = value;
+ }
+ }
+
+ public float zNear = 0.1f;
+ public float fovY = (float)Math.PI / 4;
+
+ float MoveSpeed = 0.5f;
+ float RotationSpeed = 0.02f;
+ #endregion
+
+ Context ctx;
+ Surface surf;
+
+ QuadVAO testQuad;
+ QuadVAO magnifierQuad;
+ int magTex; //mignified texture
+ go.GLBackend.Shader shade;
+ Matrix4 projectionMatrix,
+ modelviewMatrix;
+ Texture testTex;
+
+
+ void drawScene()
+ {
+ shade.Enable ();
+ //shader.LineWidth = lineWidth;
+ shade.ProjectionMatrix = projectionMatrix;
+ shade.ModelViewMatrix = modelviewMatrix;
+ shade.Color = new Vector4(1f,1f,1f,1f);
+
+ GL.ActiveTexture (TextureUnit.Texture0);
+ GL.BindTexture(TextureTarget.Texture2D, surf.texId);
+ //GL.BindTexture(TextureTarget.Texture2D, FontFace.testTexture);
+
+ testQuad.Render (PrimitiveType.TriangleStrip);
+
+ GL.BindTexture(TextureTarget.Texture2D, magTex);
+ magnifierQuad.Render (PrimitiveType.TriangleStrip);
+
+ GL.BindTexture(TextureTarget.Texture2D, 0);
+
+ //shader.Disable ();
+ }
+ glFont testFont;
+
+ protected override void OnLoad (EventArgs e)
+ {
+ base.OnLoad (e);
+
+
+ Mouse.WheelChanged += new EventHandler<MouseWheelEventArgs>(Mouse_WheelChanged);
+ Mouse.Move += new EventHandler<MouseMoveEventArgs>(Mouse_Move);
+
+ GL.Viewport (0, 0, ClientRectangle.Width, ClientRectangle.Height);
+ GL.ClearColor(0.0f, 0.0f, 0.2f, 1.0f);
+
+ //GL.Enable(EnableCap.DepthTest);
+ //GL.DepthFunc(DepthFunction.Less);
+ //GL.Enable(EnableCap.CullFace);
+ //GL.Enable(EnableCap.Texture2D);
+
+
+
+ //GL.FrontFace(FrontFaceDirection.Ccw);
+
+ //GL.Hint(HintTarget.PerspectiveCorrectionHint, HintMode.Nicest);
+ //GL.ShadeModel(ShadingModel.Smooth);
+ //GL.Hint (HintTarget.LineSmoothHint, HintMode.Nicest);
+ ErrorCode err = GL.GetError ();
+ Debug.Assert (err == ErrorCode.NoError, "OpenGL Error");
+
+ surf = new Surface (Format.Argb32, 512, 512);
+
+ testQuad = new QuadVAO (0, 0, 512, 512);
+ magnifierQuad = new QuadVAO (150, 300, 400, 400,1.1f,0.73f,0.05f,0.05f);
+
+ shade = new TexturedShader ();
+
+ projectionMatrix = Matrix4.CreateOrthographicOffCenter
+ (0, ClientRectangle.Width, ClientRectangle.Height, 0, 0, 1);
+ modelviewMatrix = Matrix4.Identity;
+
+ testTex = new Texture (rootDir + @"Images/texture/structures/639-diffuse.jpg");
+ //string[] extensions = GL.GetString(StringName.Version).Split(' ');
+ FontFace.BuildFontsList(@"/usr/share/fonts/truetype/");
+ //glFont.dumpFontsDirectories (@"/usr/share/fonts/");
+ //glFont.dumpFontsDirectories (@"/usr/share/fonts/opentype");
+ LoadInterface("Interfaces/test0.goml");
+
+ //testFont = new glFont (@"/usr/share/fonts/truetype/droid/DroidSans-Bold.ttf");
+ }
+
+ public static void DrawRoundedRectangle(Context gr, double x, double y, double width, double height, double radius)
+ {
+
+ if ((radius > height / 2) || (radius > width / 2))
+ radius = Math.Min(height / 2, width / 2);
+
+ gr.MoveTo(x, y + radius);
+ gr.Arc(x + radius, y + radius, radius, Math.PI, -Math.PI / 2);
+ gr.LineTo(x + width - radius, y);
+ gr.Arc(x + width - radius, y + radius, radius, -Math.PI / 2, 0);
+ gr.LineTo(x + width, y + height - radius);
+ gr.Arc(x + width - radius, y + height - radius, radius, 0, Math.PI / 2);
+ gr.LineTo(x + radius, y + height);
+ gr.Arc(x + radius, y + height - radius, radius, Math.PI / 2, Math.PI);
+ gr.ClosePath();
+ }
+ double angle;
+ public override void GLClear ()
+ {
+ GL.ClearColor(1.0f, 0.0f, 0.2f, 1.0f);
+ GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
+ }
+ public override void OnRender (FrameEventArgs e)
+ {
+ drawScene ();
+ }
+ protected override void OnUpdateFrame (FrameEventArgs e)
+ {
+ base.OnUpdateFrame (e);
+
+ fps = (int)RenderFrequency;
+
+ using (Context ctx = new Context (surf)) {
+ ctx.coef1 = coef1;
+ ctx.coef2 = coef2;
+ ctx.coef3 = coef3;
+ ctx.coefA = coefA;
+
+ ctx.Rectangle(new Rectangle(0,0,512,512));
+ ctx.Color = background;//new Color(1.0,0.1,0.2,1);
+ ctx.Fill ();
+ ctx.LineWidth = 1.0;
+ ctx.Color = foreground;
+ ctx.SelectFontFace ("courier new", FontSlant.Normal, FontWeight.Normal);
+ ctx.SetFontSize (6);
+ ctx.FillText ("Test d'une string a petite échelle", new Point (50, 50));
+ ctx.SetFontSize (8);
+ ctx.FillText ("Test d'une string a petite échelle", new Point (50, 60));
+ ctx.SetFontSize (10);
+ ctx.FillText ("Test d'une string a petite échelle", new Point (50, 70));
+ ctx.SetFontSize (12);
+ ctx.FillText ("Test d'une string a petite échelle", new Point (50, 85));
+ ctx.SetFontSize (14);
+ ctx.FillText ("Test d'une string a petite échelle", new Point (50, 100));
+
+ ctx.FillText ("c1: " + string.Format("{0:##.000}",coef1), new Point (300, 100));
+ ctx.FillText ("c2: " + string.Format("{0:##.000}",coef2), new Point (300, 120));
+ ctx.FillText ("c3: " + string.Format("{0:##.000}",coef3), new Point (300, 140));
+ ctx.FillText ("cA: " + string.Format("{0:##.000}",coefA), new Point (300, 160));
+
+ ctx.Rectangle(new Rectangle(10,10,40,100));
+ ctx.Stroke ();
+ ctx.SetFontSize (40);
+ ctx.FillText ("ceci est un test de string", new Point (2, 200));
+ ctx.Fill ();
+// ctx.LineWidth = 1.0;
+// ctx.MoveTo (300, 10);
+// ctx.LineTo (300, 350);
+// ctx.Color = new Color (1.0, 0.5, 0.0, 1.0);
+// ctx.Stroke ();
+// ctx.MoveTo (301, 10);
+// ctx.LineTo (301, 350);
+// ctx.Color = new Color (0.0, 0.5, 1.0, 1.0);
+// ctx.Stroke ();
+// ctx.Rectangle(new Rectangle(100,100,200,200));
+ //ctx.Clip ();
+// for (int i = 0; i < 25; i++) {
+//
+//
+// angle += Math.PI / 10000;
+// if (angle > Math.PI * 2)
+// angle = 0;
+//
+//
+// ctx.Color = new Color (1.0 / i, 1, 0, 0.1);
+// ctx.Translate (-200, -200);
+// ctx.Rotate (angle);
+// ctx.Translate (200, 200);
+//
+//
+// ctx.Rectangle (new Rectangle (0, 0, 400, 400));
+// DrawRoundedRectangle (ctx, 100, 100, 70, 70, 10);
+// ctx.FillPreserve ();
+// ctx.Color = go.Color.White;
+// ctx.Stroke ();
+// }
+ surf.Save (@"/home/jp/surf.png");
+
+ if (GL.IsTexture(magTex))
+ GL.DeleteTexture(magTex);
+
+ magTex = ctx.copyCurentSurfaceToTexture ();
+
+// GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
+// GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
+//
+ }
+
+ float inc = 0.01f;
+ if (Keyboard [Key.ShiftLeft])
+ inc = 0.1f;
+ if (Keyboard[Key.Keypad1])
+ coef1 -= inc;
+ if (Keyboard[Key.Keypad2])
+ coef2 -= inc;
+ if (Keyboard[Key.Keypad3])
+ coef3 -= inc;
+ if (Keyboard[Key.Keypad4])
+ coef1 = 0f;
+ if (Keyboard[Key.Keypad5])
+ coef2 = 0f;
+ if (Keyboard[Key.Keypad6])
+ coef3 = 0f;
+ if (Keyboard[Key.Keypad7])
+ coef1 += inc;
+ if (Keyboard[Key.Keypad8])
+ coef2 += inc;
+ if (Keyboard[Key.Keypad9])
+ coef3 += inc;
+ if (Keyboard[Key.KeypadAdd])
+ coefA += inc;
+ if (Keyboard[Key.KeypadSubtract])
+ coefA -= inc;
+ //Debug.WriteLine (fps);
+
+ }
+ protected override void OnKeyPress (KeyPressEventArgs e)
+ {
+ base.OnKeyPress (e);
+ if (e.KeyChar == 'c') {
+ if (background == Color.Black) {
+ background = Color.White;
+ foreground = Color.Black;
+ } else {
+ background = Color.Black;
+ foreground = Color.White;
+ }
+ }
+ }
+ protected override void OnResize (EventArgs e)
+ {
+ base.OnResize (e);
+ UpdateViewMatrix();
+ }
+
+ #region Mouse Handling
+ void Object_Mouse_Move(object sender, MouseMoveEventArgs e){
+ if (activeWidget == null)
+ return;
+
+ activeWidget.registerClipRect ();
+ if (activeWidget!=null) {
+ activeWidget.Left += e.XDelta;
+ activeWidget.Top += e.YDelta;
+ }
+ }
+ void Mouse_Move(object sender, MouseMoveEventArgs e)
+ {
+ if (e.XDelta != 0 || e.YDelta != 0)
+ {
+ if (e.Mouse.MiddleButton == OpenTK.Input.ButtonState.Pressed)
+ {
+ Matrix4 m = Matrix4.CreateRotationZ(-e.XDelta * RotationSpeed);
+ m *= Matrix4.CreateFromAxisAngle(-vLookPerpendicularOnXYPlane, -e.YDelta * RotationSpeed);
+ vEyeTarget = Vector3.Zero;
+ vEye = Vector3.Transform(vEye, Matrix4.CreateTranslation(-vEyeTarget) * m * Matrix4.CreateTranslation(vEyeTarget));
+ UpdateViewMatrix();
+ }
+ if (e.Mouse.RightButton == ButtonState.Pressed)
+ {
+
+ Matrix4 m = Matrix4.CreateRotationZ(-e.XDelta * RotationSpeed);
+ Matrix4 m2 = Matrix4.Rotate(vLookPerpendicularOnXYPlane, e.YDelta * RotationSpeed);
+
+ vEyeTarget = Vector3.Transform(vEyeTarget, Matrix4.CreateTranslation(-vEye) * m * m2 * Matrix4.CreateTranslation(vEye));
+
+ //vLook = Vector3.Transform(vLook, m2);
+ UpdateViewMatrix();
+
+ }
+ }
+ }
+ void Mouse_WheelChanged(object sender, MouseWheelEventArgs e)
+ {
+ float speed = MoveSpeed;
+ if (Keyboard[Key.ShiftLeft])
+ speed *= 0.1f;
+ else if (Keyboard[Key.ControlLeft])
+ speed *= 20.0f;
+
+ vLook = Vector3.NormalizeFast(vEye - vEyeTarget);
+ vEye -= vLook * e.Delta * speed;
+ UpdateViewMatrix();
+ }
+ #endregion
+
+ #region vLookCalculations
+ Vector3 vLookDirOnXYPlane
+ {
+ get
+ {
+ Vector3 v = Vector3.NormalizeFast(vEye - vEyeTarget);
+ v.Z = 0;
+ return v;
+ }
+ }
+ public Vector3 vLookPerpendicularOnXYPlane
+ {
+ get
+ {
+ Vector3 vLook = Vector3.NormalizeFast(vEye - vEyeTarget);
+ vLook.Z = 0;
+
+ Vector3 vHorizDir = Vector3.Cross(vLook, Vector3.UnitZ);
+ return vHorizDir;
+ }
+ }
+
+ void moveCamera(Vector3 v)
+ {
+ vEye += v;
+ vEyeTarget += v;
+ }
+ #endregion
+
+ public void UpdateViewMatrix()
+ {
+// Rectangle r = this.ClientRectangle;
+// GL.Viewport( r.X, r.Y, r.Width, r.Height);
+// projection = Matrix4.CreatePerspectiveFieldOfView(fovY, r.Width / (float)r.Height, zNear, zFar);
+// GL.MatrixMode(MatrixMode.Projection);
+// GL.LoadIdentity();
+//
+// GL.LoadMatrix(ref projection);
+//
+// modelview = Matrix4.LookAt(vEye, vEyeTarget, Vector3.UnitZ);
+// GL.MatrixMode(MatrixMode.Modelview);
+// GL.LoadIdentity();
+// GL.LoadMatrix(ref modelview);
+ }
+ [STAThread]
+ static void Main ()
+ {
+ Console.WriteLine ("starting example");
+
+ using (GOLIBTestglb win = new GOLIBTestglb( )) {
+ win.Run (30.0);
+ }
+ }
+ }
+}
+//using (Context ctx = new Context (surf)) {
+// //for (int i = 0; i < 150; i++) {
+//
+//
+// // angle += Math.PI / 100000;
+// // if (angle > Math.PI * 2)
+// // angle = 0;
+// //GL.
+// //drawScene();
+//
+// // ctx.Color = new Color (1.0/i, 1, 0, 1);
+// // ctx.Translate (-512, -400);
+// // ctx.Rotate (angle);
+// // ctx.Translate (512, 400);
+// ctx.LineWidth = 1.0;
+// ctx.Color = go.Color.LightBlue.AdjustAlpha(0.2);
+// // ctx.MoveTo (100, 100);
+// // ctx.LineTo (150, 150);
+// // ctx.LineTo (300, 100);
+// // ctx.LineTo (150, 200);
+// // ctx.LineTo (500, 200);
+// // ctx.LineTo (400, 100);
+// // ctx.LineTo (600, 100);
+// // ctx.LineTo (600, 600);
+// // ctx.LineTo (200, 600);
+// // ctx.LineTo (300, 300);
+// // ctx.LineTo (100, 300);
+// // //ctx.ClosePath ();
+// //ctx.Rectangle(new go.Rectangle(100,600,60,80));
+//
+// DrawRoundedRectangle (ctx, 200, 200, 70, 70,10);
+// // DrawRoundedRectangle (ctx, 300, 300, 70, 70,5);
+// // DrawRoundedRectangle (ctx, 400, 400, 70, 70,25);
+// // DrawRoundedRectangle (ctx, 500, 500, 70, 70,25);
+// // DrawRoundedRectangle (ctx, 600, 600, 100, 100,25);
+//
+//
+// //**** concave shape
+//
+// // ctx.LineTo (110, 200);
+// // ctx.LineTo (400, 200);
+// // ctx.LineTo (400, 100);
+// // ctx.LineTo (200, 100);
+// // ctx.LineTo (200, 50);
+// // ctx.LineTo (500, 50);
+// // ctx.LineTo (500, 200);
+// // ctx.LineTo (400, 300);
+// // ctx.LineTo (100, 300);
+// // ctx.LineTo (50, 200);
+// ctx.FillPreserve ();
+// //*****************************
+//
+// ctx.Color = go.Color.White;
+// //ctx.Stroke ();
+// // ctx.LineTo (500, 50);
+// // ctx.LineTo (750, 500);
+// // ctx.LineTo (750, 50);
+// // ctx.MoveTo (100, 100);
+// // ctx.LineTo (200, 200);
+// // ctx.LineTo (100, 400);
+// // ctx.LineTo (300, 400);
+// // //ctx.LineTo (250, 300);
+// // ctx.Arc (300, 600, 100, 0, Math.PI);
+// ctx.Stroke ();
+//}
+////}
namespace go
{
- public enum FontStyle
- {
- Normal,
- Bold,
- Italic,
- Underlined
- }
public class Font
{
#region CTOR
if (!string.IsNullOrEmpty (ClassName))
break;
if (CurrentGOMLPath.StartsWith ("#"))
- ClassName = Path.GetFileNameWithoutExtension (CurrentGOMLPath.Substring (1));
+ ClassName = System.IO.Path.GetFileNameWithoutExtension (CurrentGOMLPath.Substring (1));
else
- ClassName = Path.GetFileNameWithoutExtension (CurrentGOMLPath);
+ ClassName = System.IO.Path.GetFileNameWithoutExtension (CurrentGOMLPath);
break;
}
}
newClassName = reader.GetAttribute ("Class");
if (string.IsNullOrEmpty (newClassName)) {
if (path.StartsWith ("#"))
- newClassName = Path.GetFileNameWithoutExtension (path.Substring (1));
+ newClassName = System.IO.Path.GetFileNameWithoutExtension (path.Substring (1));
else
- newClassName = Path.GetFileNameWithoutExtension (path);
+ newClassName = System.IO.Path.GetFileNameWithoutExtension (path);
}
curType = Type.GetType ("go." + root);
--- /dev/null
+using System;
+using OpenTK.Graphics.OpenGL;
+
+namespace go.GLBackend
+{
+ public class ClipShader : Shader
+ {
+ public ClipShader ()
+ {
+ vertSource = @"
+ #version 130
+
+ precision highp float;
+
+ uniform mat4 projection_matrix;
+ uniform mat4 modelview_matrix;
+
+ in vec2 in_position;
+
+ void main(void)
+ {
+ gl_Position = projection_matrix * modelview_matrix * vec4(in_position,0, 1);
+ }";
+
+ fragSource = @"
+ #version 130
+ precision highp float;
+
+ out vec4 out_frag_color;
+
+ void main(void)
+ {
+ out_frag_color = vec4(1.0,1.0,1.0,1.0);
+ }";
+
+ Compile ();
+ }
+ }
+}
+
--- /dev/null
+#define MPERF
+//#define GPU_TIME_MSR
+
+using System;
+using OpenTK.Graphics.OpenGL;
+using OpenTK;
+using System.Collections.Generic;
+using System.Linq;
+using System.Diagnostics;
+using System.Drawing.Imaging;
+
+
+
+namespace go.GLBackend
+{
+ public class Context : IDisposable
+ {
+ #region CTOR
+ public Context (Surface _surf)
+ {
+ surf = _surf;
+
+ saveGLConfig ();
+
+ createStencilTexture ();
+
+ fboId = createFbo (surf.texId);
+
+ projectionMatrix = Matrix4.CreateOrthographicOffCenter
+ (0, surf.width, surf.height, 0, 0, 1);
+ modelviewMatrix = Matrix4.Identity;
+
+ if (shader == null)
+ shader = new Shader ();
+ if (texturedShader == null)
+ texturedShader = new TexturedShader ();
+ if (clipShader == null)
+ clipShader = new ClipShader ();
+ if (fontShader == null)
+ fontShader = new FontShader ();
+
+
+ GL.Viewport (0, 0, surf.width, surf.height);
+ GL.PrimitiveRestartIndex (int.MaxValue);
+ GL.Enable (EnableCap.PrimitiveRestart);
+ GL.Enable (EnableCap.Blend);
+ GL.BlendFunc (BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
+
+ //GL.BindFramebuffer(FramebufferTarget.Framebuffer, fboId);
+
+ // GL.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ // GL.Clear(ClearBufferMask.ColorBufferBit);
+ }
+ #endregion
+
+ #if (DEBUG && MPERF)
+ Stopwatch sw_fill = new Stopwatch ();
+ Stopwatch sw_stroke = new Stopwatch ();
+ #endif
+
+ #if GPU_TIME_MSR
+ ulong gpuTime = 0;
+ ulong gpuTimeCpt = 0;
+ #endif
+
+ public float coef1 = 1.0f;
+ public float coef2 = 0.5f;
+ public float coef3 = 0.0f;
+ public float coefA = 1.0f;
+
+ static Shader shader;
+ static Shader clipShader;
+ static Shader texturedShader;
+ static FontShader fontShader;
+
+ static List<glFont> fontsCache = new List<glFont>();
+
+ #region Private Fields
+ Surface surf;
+ Surface sourceSurface;//should be a pattern object from which surf would be derrived
+
+ double lineWidth = 1.0;
+ Color color = Color.White;
+ LineCap lineCap = LineCap.Butt;
+ LineJoin lineJoint = LineJoin.Miter;
+
+ FontFace fontFace;
+ uint fontSize = 10;
+ //path building temp fields
+ Vector2 curPos = new Vector2(0f,0f);
+ List<Path> pathes = new List<Path> ();
+ Path cpath;//current path
+
+ int fboId;
+ int stencilTexId;
+ VertexArrayObject vao;
+
+ Matrix4 projectionMatrix,
+ modelviewMatrix;
+
+ bool stencilTest = false;
+
+ VertexArrayObject paint_vao; //quad used to paint source on context
+
+ //path limits used in fill
+ float minX,maxX,minY,maxY,
+ polyWidth, polyHeight;
+
+ #endregion
+
+ #region Public properties
+ public double LineWidth {
+ get { return lineWidth; }
+ set { lineWidth = value; }
+ }
+ public Color Color {
+ get { return color; }
+ set { color = value; }
+ }
+ public LineCap LineCap {
+ get { return lineCap;}
+ set {lineCap = value;}
+ }
+ public LineJoin LineJoint {
+ get {return lineJoint;}
+ set {lineJoint = value;}
+ }
+ #endregion
+
+ #region Private functions
+ int createFbo(int texID)
+ {
+ //GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
+ int fbo;
+ GL.GenFramebuffers(1,out fbo);
+ GL.BindFramebuffer(FramebufferTarget.Framebuffer, fbo);
+ GL.FramebufferTexture2D(FramebufferTarget.Framebuffer,
+ FramebufferAttachment.ColorAttachment0,
+ TextureTarget.Texture2D,texID,0);
+
+ //GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
+ FramebufferErrorCode fbErr = GL.CheckFramebufferStatus (FramebufferTarget.Framebuffer);
+
+ switch (fbErr) {
+ case FramebufferErrorCode.FramebufferUndefined:
+ break;
+ case FramebufferErrorCode.FramebufferComplete:
+ //Debug.WriteLine ("FBO complete");
+ break;
+ case FramebufferErrorCode.FramebufferIncompleteAttachment:
+ Debug.WriteLine ("FBO incomplete attachment");
+ break;
+ case FramebufferErrorCode.FramebufferIncompleteMissingAttachment:
+ Debug.WriteLine ("FBO missing attachment");
+ break;
+ default:
+ Debug.WriteLine ("FBO error");
+ break;
+ }
+ return fbo;
+ }
+ public int copyCurentSurfaceToTexture()
+ {
+ //create a new fbo to blit to with an empty texture
+ Surface tmp = surf.CreateSimilar ();
+ int dstFbo = createFbo (tmp.texId);//we are binded to new fbo (read&write)
+ //bind read to Context fbo;
+ GL.BindFramebuffer (FramebufferTarget.ReadFramebuffer, fboId);
+ GL.BindFramebuffer (FramebufferTarget.DrawFramebuffer, dstFbo);
+
+ GL.BlitFramebuffer (0, 0, surf.width, surf.height, 0, 0, surf.width, surf.height,
+ ClearBufferMask.ColorBufferBit,BlitFramebufferFilter.Nearest);
+
+ //bind write fbo to Context
+ GL.BindFramebuffer (FramebufferTarget.Framebuffer, fboId);
+ //delete temp fbo
+ GL.DeleteFramebuffer (dstFbo);
+ return tmp.texId;
+ }
+ void createStencilTexture(){
+ stencilTexId = GL.GenTexture();
+ GL.BindTexture(TextureTarget.Texture2D, stencilTexId);
+ GL.TexImage2D(TextureTarget.Texture2D,0,
+ PixelInternalFormat.R8, surf.width, surf.height,0,
+ OpenTK.Graphics.OpenGL.PixelFormat.Red, PixelType.UnsignedByte,IntPtr.Zero);
+
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
+ GL.BindTexture(TextureTarget.Texture2D, 0);
+ }
+ void clear_path()
+ {
+ pathes.Clear ();
+ curPos = new Vector2 (0f, 0f);
+ cpath = null;
+ }
+ void addPath(Path _path){
+ if (_path == null)
+ return;
+ if (_path.Count > 1)
+ pathes.Add (_path);
+ }
+ //TODO: 360° will fail
+ double NormalizeAngle(double a)
+ {
+ double res = a % (2*Math.PI);
+ return res < 0 ? res + 2*Math.PI : res;
+ }
+ #endregion
+
+ #region Public functions
+ #region Main drawing functions
+ public void Stroke()
+ {
+ stroke_internal ();
+ clear_path ();
+ }
+ public void StrokePreserve()
+ {
+ stroke_internal ();
+ }
+ public void Fill()
+ {
+ fill_internal ();
+ clear_path ();
+ }
+ public void FillPreserve()
+ {
+ fill_internal ();
+ }
+ public void Paint()
+ {
+ if (paint_vao == null)
+ return;
+ texturedShader.Enable ();
+ //shader.LineWidth = lineWidth;
+ texturedShader.ProjectionMatrix = projectionMatrix;
+ texturedShader.ModelViewMatrix = modelviewMatrix;
+ texturedShader.Color = new Vector4(1f,1f,1f,1f);
+
+ GL.ActiveTexture (TextureUnit.Texture0);
+ GL.BindTexture (TextureTarget.Texture2D, sourceSurface.texId);
+
+ paint_vao.Render (PrimitiveType.TriangleStrip);
+
+ GL.BindTexture (TextureTarget.Texture2D, 0);
+
+ texturedShader.Disable ();
+ }
+ public void SetSourceSurface (Surface _source, int x, int y)
+ {
+ sourceSurface = _source;
+
+ if (paint_vao != null)
+ paint_vao.Dispose ();
+
+
+ paint_vao = new QuadVAO (x,y,sourceSurface.width,sourceSurface.height);
+ }
+ #region Clipping
+ public void Clip()
+ {
+ clip_internal ();
+ clear_path ();
+ }
+ public void ClipPreserve()
+ {
+ clip_internal ();
+ clear_path ();
+ }
+ public void ResetClip()
+ {
+ stencilTest = false;
+
+ GL.FramebufferTexture2D(FramebufferTarget.Framebuffer,
+ FramebufferAttachment.ColorAttachment0,
+ TextureTarget.Texture2D,stencilTexId,0);
+
+
+ GL.Clear (ClearBufferMask.ColorBufferBit);
+
+ GL.FramebufferTexture2D(FramebufferTarget.Framebuffer,
+ FramebufferAttachment.ColorAttachment0,
+ TextureTarget.Texture2D,surf.texId,0);
+ }
+ #endregion
+
+ #region Fonts & text handling
+ public void SelectFontFace(string _fontName, FontSlant _slant, FontWeight _weight){
+ Font tmp = _fontName;
+ switch (_slant) {
+ case FontSlant.Italic:
+ tmp.Style |= FontStyle.Italic;
+ break;
+ case FontSlant.Oblique:
+ tmp.Style |= FontStyle.Oblique;
+ break;
+ }
+ if (_weight == FontWeight.Bold)
+ tmp.Style |= FontStyle.Bold;
+
+ fontFace = FontFace.SearchFont (tmp);
+ }
+ public void SetFontSize(uint _fontSize){
+ fontSize = _fontSize;
+ if (!fontFace.glyphesCache.ContainsKey(fontSize))
+ fontFace.buildGlyphesTextures (fontSize, 0, 0xFF);
+ }
+ public FontExtents FontExtents {
+ get {
+ return fontFace.originalFontExtents;
+ }
+ }
+ public TextExtents TextExtents(string s)
+ {
+ TextExtents te = new go.GLBackend.TextExtents ();
+
+ int penX = 0,
+ penY = 0;
+
+ for (int i = 0; i < s.Length; i++) {
+ uint c = (uint)s [i];
+ glGlyph g = fontFace.glyphesCache [fontSize] [c];
+ penX += (int)g.advanceX;
+ penY += (int)g.advanceY;
+ }
+
+ te.XAdvance = penX;
+ te.YAdvance = penY;
+ return te;
+ }
+ public void FillText(string text, Point _pt)
+ {
+ buildTextVAO (text,_pt);
+
+ int backTex = copyCurentSurfaceToTexture ();
+
+ fontShader.Enable ();
+ //shader.LineWidth = lineWidth;
+ fontShader.ProjectionMatrix = projectionMatrix;
+ fontShader.ModelViewMatrix = modelviewMatrix;
+ fontShader.Color = new Vector4(
+ (float)color.R,
+ (float)color.G,
+ (float)color.B,
+ (float)color.A);
+ fontShader.Resolution = new Vector2 (surf.width, surf.height);
+ fontShader.coef1 = coef1;
+ fontShader.coef2 = coef2;
+ fontShader.coef3 = coef3;
+ fontShader.coefA = coefA;
+// shader.StencilTest = stencilTest;
+//
+// if (stencilTest) {
+// shader.Resolution = new Vector2 (surf.width, surf.height);
+// GL.ActiveTexture (TextureUnit.Texture0);
+// GL.BindTexture (TextureTarget.Texture2D, stencilTexId);
+// }
+
+ GL.ActiveTexture (TextureUnit.Texture0);
+ GL.BindTexture (TextureTarget.Texture2D, curFontTex);
+ GL.ActiveTexture (TextureUnit.Texture1);
+ GL.BindTexture (TextureTarget.Texture2D, backTex);
+
+ vao.Render (PrimitiveType.TriangleStrip);
+ vao.Dispose ();
+
+ // #if DEBUG
+ // ErrorCode err = GL.GetError ();
+ // if (err != ErrorCode.NoError)
+ // Debug.WriteLine ("Stroke_internal error: " + err.ToString ());
+ // #endif
+
+ fontShader.Disable ();
+
+ GL.BindTexture (TextureTarget.Texture2D, 0);
+ GL.ActiveTexture (TextureUnit.Texture0);
+ GL.BindTexture (TextureTarget.Texture2D, 0);
+
+ //destroy background texture
+ GL.DeleteTexture (backTex);
+ //GL.Enable (EnableCap.Blend);
+ }
+ #endregion
+
+ #endregion
+
+
+
+ #region Path handling functions
+ public void MoveTo(double x, double y)
+ {
+ addPath (cpath);
+ cpath = new Path ();
+ curPos = new Vector2 ((float)x, (float)y);
+ }
+ public void LineTo(double x, double y)
+ {
+ if (cpath==null)
+ cpath = new Path ();
+ if (cpath.Count == 0)
+ cpath.Add (curPos);
+ curPos = new Vector2 ((float)x, (float)y);
+ cpath.Add (curPos);
+ }
+ public void Rectangle(Rectangle r)
+ {
+ MoveTo (r.X, r.Y);
+ LineTo (r.Right, r.Y);
+ LineTo (r.Right, r.Bottom);
+ LineTo (r.X, r.Bottom);
+ ClosePath ();
+ }
+ public void Arc(double xc, double yc, double radius, double angle1, double angle2)
+ {
+ angle1 = NormalizeAngle (angle1);
+ angle2 = NormalizeAngle (angle2);
+
+ if (angle1 > angle2)
+ angle2 += Math.PI * 2.0;
+ double a = angle1,
+ //step = Math.PI/16;
+ step =Math.PI * 2/(radius+20);
+
+ Vector2 v = new Vector2 ((float)(Math.Cos (a) * radius + xc), (float)(Math.Sin (a) * radius + yc));
+ if (v!=curPos)
+ cpath.Add (v);
+ int cpt = 0;
+ while(true){
+ if (a<angle2){
+ a+=step;
+ if (a > angle2)
+ break;
+ //a = angle2;
+ }else
+ break;
+ cpt++;
+// if (a == angle2) {//add a point very close to a to get good termination angle
+// v = new Vector2 ((float)(Math.Cos (a-0.001) * radius + xc), (float)(Math.Sin (a-0.001) * radius + yc));
+// cpath.Add (v);
+// }
+
+ v = new Vector2 ((float)(Math.Cos (a) * radius + xc), (float)(Math.Sin (a) * radius + yc));
+ cpath.Add (v);
+
+ }
+ curPos = cpath [cpath.Count - 1];
+ }
+ public void ClosePath()
+ {
+ if (cpath == null)
+ return;
+ if (cpath.Count < 3)//cannot close path with less than 3 points
+ return;
+
+ cpath.IsClosed = true;
+
+ MoveTo (cpath [0].X, cpath [0].Y);
+ }
+ #endregion
+
+ #region Transformations
+ public void Translate(double tx, double ty)
+ {
+ modelviewMatrix *= Matrix4.CreateTranslation ((float)tx, (float)ty, 0f);
+ }
+ public void Scale(double sx, double sy)
+ {
+ modelviewMatrix *= Matrix4.CreateScale ((float)sx, (float)sy, 0f);
+ }
+ public void Rotate(double angle){
+ modelviewMatrix *= Matrix4.CreateRotationZ ((float)angle);
+ }
+ #endregion
+ #endregion
+
+ //temp Lists used to build arrays for vao
+ List<Vector2> vertices = new List<Vector2> ();
+ List<int> indices = new List<int> ();
+ List<Vector2> texCoords = new List<Vector2> ();
+ int idxOffset = 0; //offset in vertices array between pathes
+
+
+ void initVAOsCache()
+ {
+ if (vertices != null)
+ return;
+ vertices = new List<Vector2> ();
+ indices = new List<int> ();
+ texCoords = new List<Vector2> ();
+ idxOffset = 0;
+ }
+ void flush(){
+ vao = new VertexArrayObject (
+ vertices.ToArray (),
+ texCoords.ToArray (),
+ indices.ToArray ());
+
+ vertices = null;
+ indices = null;
+ texCoords = null;
+ }
+
+ void stroke_internal()
+ {
+ buildStrokeVAOs ();
+
+ #if GPU_TIME_MSR
+ ulong gpuTimeStart, gpuTimeStop;
+ gpuTimeStart = (ulong)GL.GetInteger64 (GetPName.Timestamp);
+ #endif
+
+ shader.Enable ();
+ //shader.LineWidth = lineWidth;
+ shader.ProjectionMatrix = projectionMatrix;
+ shader.ModelViewMatrix = modelviewMatrix;
+ shader.Color = new Vector4(
+ (float)color.R,
+ (float)color.G,
+ (float)color.B,
+ (float)color.A);
+ shader.StencilTest = stencilTest;
+
+ if (stencilTest) {
+ shader.Resolution = new Vector2 (surf.width, surf.height);
+ GL.ActiveTexture (TextureUnit.Texture0);
+ GL.BindTexture (TextureTarget.Texture2D, stencilTexId);
+ }
+
+ vao.Render (PrimitiveType.TriangleStrip);
+ vao.Dispose ();
+
+// #if DEBUG
+// ErrorCode err = GL.GetError ();
+// if (err != ErrorCode.NoError)
+// Debug.WriteLine ("Stroke_internal error: " + err.ToString ());
+// #endif
+
+ shader.Disable ();
+
+ GL.BindTexture (TextureTarget.Texture2D, 0);
+
+ #if GPU_TIME_MSR
+ gpuTimeStop = (ulong)GL.GetInteger64 (GetPName.Timestamp);
+ Debug.WriteLine(gpuTimeStop - gpuTimeStart);
+ #endif
+ }
+ void fill_internal()
+ {
+ buildFillVAOs ();
+
+ shader.Enable ();
+ //shader.LineWidth = lineWidth;
+ shader.ProjectionMatrix = projectionMatrix;
+ shader.ModelViewMatrix = modelviewMatrix;
+ shader.Color = new Vector4(
+ (float)color.R,
+ (float)color.G,
+ (float)color.B,
+ (float)color.A);
+ shader.StencilTest = stencilTest;
+
+ if (stencilTest) {
+ shader.Resolution = new Vector2 (surf.width, surf.height);
+ GL.ActiveTexture (TextureUnit.Texture0);
+ GL.BindTexture (TextureTarget.Texture2D, stencilTexId);
+ }
+
+ vao.Render (PrimitiveType.Triangles);
+ vao.Dispose ();
+
+ shader.Disable ();
+
+ GL.BindTexture (TextureTarget.Texture2D, 0);
+ }
+ void clip_internal()
+ {
+ GL.FramebufferTexture2D(FramebufferTarget.Framebuffer,
+ FramebufferAttachment.ColorAttachment0,
+ TextureTarget.Texture2D,stencilTexId,0);
+
+ if (!stencilTest)
+ GL.Clear (ClearBufferMask.ColorBufferBit);
+ stencilTest = true;
+
+ buildFillVAOs ();
+
+ clipShader.Enable ();
+ //shader.LineWidth = lineWidth;
+ clipShader.ProjectionMatrix = projectionMatrix;
+ clipShader.ModelViewMatrix = modelviewMatrix;
+
+ vao.Render (PrimitiveType.Triangles);
+ vao.Dispose ();
+
+ clipShader.Disable ();
+
+ GL.FramebufferTexture2D(FramebufferTarget.Framebuffer,
+ FramebufferAttachment.ColorAttachment0,
+ TextureTarget.Texture2D,surf.texId,0);
+ }
+
+ void buildFillVAOs()
+ {
+ #if (DEBUG && MPERF)
+ sw_fill.Start();
+ #endif
+
+ addPath (cpath);
+
+ initVAOsCache ();
+
+ float hlw = (float)lineWidth / 2.0f;//half line width
+
+ Vector2 vDir,vDir2;
+ bool genTexCoords = false;
+
+ for (int j = 0; j < pathes.Count; j++) {
+ Path path = new Path(pathes[j]);
+ //keep an array containing real vertex indice
+ List<int> vertIdx = new List<int> (Enumerable.Range(0,path.Count));
+
+ #region get polygon bounds for texture mapping
+ if (genTexCoords){
+ minX = float.MaxValue;
+ maxX = float.MinValue;
+ minY = float.MaxValue;
+ maxY = float.MinValue;
+
+ foreach (Vector2 p in path) {
+ if (p.X < minX)
+ minX = p.X;
+ if (p.Y < minY)
+ minY = p.Y;
+ if (p.X > maxX)
+ maxX = p.X;
+ if (p.Y > maxY)
+ maxY = p.Y;
+ }
+ polyWidth = maxX - minX;
+ polyHeight = maxY - minY;
+ }
+ #endregion
+
+ vertices.AddRange (path);//we only play on indices
+ int ptrS = 0, ptrS1, ptrS2; //index du sommet dans le path
+ while (path.Count > 3) {
+ if (ptrS == path.Count)
+ ptrS = 0;
+
+ if (ptrS < path.Count - 2) {
+ ptrS1 = ptrS + 1;
+ ptrS2 = ptrS + 2;
+ } else if (ptrS < path.Count - 1) {
+ ptrS1 = ptrS + 1;
+ ptrS2 = 0;
+ } else {
+ ptrS1 = 0;
+ ptrS2 = 1;
+ }
+
+ //should test only concavity points if any
+ vDir = Vector2.NormalizeFast (path [ptrS1] - path [ptrS]);
+ vDir2 = Vector2.NormalizeFast (path [ptrS2] - path [ptrS]);
+
+ float dotP = Vector2.Dot (vDir.PerpendicularLeft, vDir2);
+ //double angle = Math.Acos((double)dotP);
+//
+// Debug.WriteLine (dotP);
+// Debug.WriteLine (angle);
+
+ if (dotP <= 0) {
+ //triangle is invalid
+ ptrS++;
+ continue;
+ }
+
+ //check if no other points of path is inside tri
+// bool triangleIsValid = true;
+// int i = ptrS + 3;
+// if (i >= path.Count)
+// i -= path.Count;
+// while (i != ptrS) {
+// if (PointInTriangle (path [i],path [ptrS] , path [ptrS1], path [ptrS2])) {
+// ptrS++;
+// triangleIsValid = false;
+// break;
+// }
+// i++;
+// if (i == path.Count)
+// i = 0;
+// }
+// if (!triangleIsValid)
+// continue;
+ //triangle is valid, add tri to primitive to draw
+ //and remove middle sommet from path[];
+ addFillTriangle (j, vertIdx [ptrS], vertIdx [ptrS1], vertIdx [ptrS2]);
+
+ path.RemoveAt (ptrS1);
+ vertIdx.RemoveAt (ptrS1);
+ }
+ if (path.Count == 3)
+ addFillTriangle (j, vertIdx [0], vertIdx [1], vertIdx [2]);
+
+ if (j < pathes.Count - 1) {
+ idxOffset += pathes[j].Count;
+ }
+ }
+ flush ();
+
+ #if (DEBUG && MPERF)
+ sw_fill.Stop();
+ #endif
+ }
+
+ int curFontTex;
+ void buildTextVAO(string text, Point pt)
+ {
+ initVAOsCache ();
+
+ int penX = pt.X,
+ penY = pt.Y + (int)fontFace.originalFontExtents.Ascent;
+
+ for (int i = 0; i < text.Length; i++) {
+ uint c = (uint)text [i];
+ glGlyph g = fontFace.glyphesCache [fontSize] [c];
+ curFontTex = g.texId;
+ vertices.Add (new Vector2(penX + g.bmpLeft, penY - g.bmpTop));
+ vertices.Add (new Vector2(penX + g.bmpLeft, penY - g.bmpTop + g.dims.Height));
+ vertices.Add (new Vector2(penX + g.bmpLeft + g.dims.Width, penY - g.bmpTop));
+ vertices.Add (new Vector2(penX + g.bmpLeft + g.dims.Width, penY - g.bmpTop + g.dims.Height));
+ indices.Add (int.MaxValue);//primitive restart
+ indices.Add (i*4);
+ indices.Add (i*4 + 1);
+ indices.Add (i*4 + 2);
+ indices.Add (i*4 + 3);
+ texCoords.Add (new Vector2(g.texX,g.texY));
+ texCoords.Add (new Vector2(g.texX,g.texY + g.texHeight));
+ texCoords.Add (new Vector2(g.texX + g.texWidth,g.texY));
+ texCoords.Add (new Vector2(g.texX + g.texWidth,g.texY + g.texHeight));
+
+ penX += (int)g.advanceX;
+ penY += (int)g.advanceY;
+ }
+
+ flush ();
+ }
+ void buildStrokeVAOs()
+ {
+ addPath (cpath);
+
+ initVAOsCache ();
+
+ float hlw = (float)lineWidth / 2.0f;//half line width
+
+ Vector2 vDir,vDir2, vPerp;
+ float lPerp;
+ int i;
+ //current offset in index
+ for (int j = 0; j < pathes.Count; j++) {
+ Path path = pathes[j];
+ for (i = 0; i < path.Count; i++) {
+ lPerp = hlw;
+ vDir2 = Vector2.Zero;
+
+ if (i < path.Count - 1) {
+ vDir = Vector2.Normalize (path [i + 1] - path [i]);
+ if (i > 0) {
+ vDir2 = Vector2.Normalize (path [i] - path [i - 1]);
+ } else if (path.IsClosed)
+ vDir2 = Vector2.Normalize (path [0] - path [path.Count - 1]);
+ } else {
+ vDir = Vector2.Normalize (path [i] - path [i - 1]);
+ if (path.IsClosed)
+ vDir2 = Vector2.Normalize (path [0]-path [i]);
+ }
+
+ vPerp = Vector2.Normalize(vDir+vDir2).PerpendicularLeft;
+
+ if (vDir2 != Vector2.Zero) {
+ double dotP = Vector2.Dot (vDir.PerpendicularLeft, vPerp);
+ double angle = Math.Acos(dotP);
+ double x = Math.Tan (angle) * hlw;
+
+ if (dotP == 0)
+ lPerp = hlw;
+ else
+ lPerp = (float)Math.Sqrt (Math.Pow (x, 2) + Math.Pow (hlw, 2));
+ }
+
+ vertices.Add (path [i] + vPerp * (float)lPerp);
+ vertices.Add (path [i] - vPerp * (float)lPerp);
+ indices.Add (idxOffset + i*2);
+ indices.Add (idxOffset + i*2 + 1);
+ texCoords.Add (Vector2.Zero);
+ texCoords.Add (Vector2.One);
+ }
+ if (path.IsClosed) {
+ indices.Add (idxOffset);
+ indices.Add (idxOffset+1);
+ texCoords.Add (Vector2.Zero);
+ texCoords.Add (Vector2.One);
+ }
+ if (j < pathes.Count - 1) {
+ indices.Add (int.MaxValue); //restart primitive idex
+ idxOffset += path.Count * 2;
+ }
+ }
+ flush ();
+ }
+
+ void addFillTriangle(int pathIdx, int vx1, int vx2, int vx3){
+ addFillVertex (pathIdx, vx1);
+ addFillVertex (pathIdx, vx2);
+ addFillVertex (pathIdx, vx3);
+ }
+
+ void addFillVertex(int pathIdx, int vx){
+ Vector2 p = pathes [pathIdx] [vx];
+ indices.Add (idxOffset + vx);
+ //texCoords.Add (new Vector2(1.0f/polyWidth*(p.X-minX),1.0f/polyHeight*(p.Y-minY)));
+ }
+
+ float sign (Vector2 p1, Vector2 p2, Vector2 p3)
+ {
+ return (p1.X - p3.X) * (p2.Y - p3.Y) - (p2.X - p3.X) * (p1.Y - p3.Y);
+ }
+ bool PointInTriangle (Vector2 pt, Vector2 v1, Vector2 v2, Vector2 v3)
+ {
+ bool b1, b2, b3;
+
+ b1 = sign(pt, v1, v2) < 0.0f;
+ b2 = sign(pt, v2, v3) < 0.0f;
+ b3 = sign(pt, v3, v1) < 0.0f;
+
+ return ((b1 == b2) && (b2 == b3));
+ }
+
+ #region GL Ctx Save and restore
+ int savedFbo,
+ savedPriRstIdx,
+ savedBlendSrc,
+ savedBlendDst;
+ int[] viewport = new int[4];
+ float[] savedClsColor = new float[4];
+ bool savedBlend,savedPriRstCap;
+ void saveGLConfig(){
+ GL.GetInteger (GetPName.FramebufferBinding, out savedFbo);
+ GL.GetInteger ((GetPName)All.PrimitiveRestartIndex, out savedPriRstIdx);
+ GL.GetBoolean ((GetPName)All.PrimitiveRestart, out savedPriRstCap);
+ GL.GetInteger(GetPName.Viewport, viewport);
+ GL.GetFloat (GetPName.ColorClearValue, savedClsColor);
+ GL.GetBoolean (GetPName.Blend, out savedBlend);
+ GL.GetInteger (GetPName.BlendSrc, out savedBlendSrc);
+ GL.GetInteger (GetPName.BlendDst, out savedBlendDst);
+ }
+ void restoreGLConfig(){
+ GL.BindFramebuffer(FramebufferTarget.Framebuffer, savedFbo);
+
+ GL.Viewport (viewport[0],viewport[1],viewport[2],viewport[3]);
+ GL.PrimitiveRestartIndex (savedPriRstIdx);
+ GL.ClearColor (savedClsColor [0], savedClsColor [1], savedClsColor [2], savedClsColor [3]);
+ if (!savedBlend)
+ GL.Disable (EnableCap.Blend);
+ if (!savedPriRstCap)
+ GL.Disable (EnableCap.PrimitiveRestart);
+ GL.BlendFunc ((BlendingFactorSrc) savedBlendSrc,(BlendingFactorDest)savedBlendDst);
+ }
+ #endregion
+
+ #region IDisposable implementation
+
+ public void Dispose ()
+ {
+ restoreGLConfig ();
+
+ if (GL.IsFramebuffer (fboId))
+ GL.DeleteFramebuffer (fboId);
+ if (GL.IsTexture(stencilTexId))
+ GL.DeleteTexture(stencilTexId);
+ }
+
+ #endregion
+
+ }
+}
+
--- /dev/null
+using System;
+
+
+namespace go.GLBackend
+{
+ public class Font
+ {
+ public Font ()
+ {
+ }
+
+ public Font (string name, FontSlant fs, FontWeight fw)
+ {
+ _name = name;
+ switch (fs) {
+ case FontSlant.Italic:
+ Style |= FontStyle.Italic;
+ break;
+ case FontSlant.Oblique:
+ Style |= FontStyle.Oblique;
+ break;
+ }
+ if (fw == FontWeight.Bold)
+ Style |= FontStyle.Bold;
+ }
+
+ string _name = "droid";
+ FontStyle _style = FontStyle.Normal;
+ FontFlag _flags = FontFlag.None;
+
+ int _size = 10;
+
+ public string Name {
+ get { return _name; }
+ set { _name = value; }
+ }
+ public FontStyle Style {
+ get { return _style; }
+ set { _style = value; }
+ }
+ public FontFlag Flags {
+ get { return _flags; }
+ set { _flags = value; }
+ }
+ public FontSlant Slant {
+ get{
+ if ((Style & FontStyle.Italic) == FontStyle.Italic)
+ return FontSlant.Italic;
+ if ((Style & FontStyle.Oblique) == FontStyle.Oblique)
+ return FontSlant.Oblique;
+ return FontSlant.Normal;
+ }
+ }
+ public FontWeight Wheight {
+ get{ return (Style & FontStyle.Bold) == FontStyle.Bold ? FontWeight.Bold : FontWeight.Normal; }
+ }
+ public int Size {
+ get { return _size; }
+ set { _size = value; }
+ }
+
+ #region Operators
+ public static implicit operator string(Font c)
+ {
+ return c.ToString();
+ }
+ public static implicit operator Font(string s)
+ {
+ Font f = new Font ();
+
+ if (!string.IsNullOrEmpty (s)) {
+ f.Name = "";
+ string[] attribs = s.TrimStart().TrimEnd().Split(',');
+ for (int i = 0; i < attribs.Length; i++) {
+ FontFlag fl;
+ FontStyle fs;
+ int sz;
+ if (Enum.TryParse<FontFlag> (attribs [i], true, out fl))
+ f.Flags |= fl;
+ else if (Enum.TryParse<FontStyle> (attribs [i], true, out fs))
+ f.Style |= fs;
+ else if (int.TryParse (attribs [i], out sz))
+ f.Size = sz;
+ else
+ f.Name += attribs[i] + " ";
+ }
+ f.Name = f.Name.Trim();
+ }
+
+ return f;
+ }
+ #endregion
+ public string FontFaceString
+ {
+ get {
+ string tmp = Name;
+ if (Style != FontStyle.Normal)
+ tmp += "," + Style.ToString ();
+ if (Flags != FontFlag.None)
+ tmp += "," + Flags.ToString ();
+ return tmp;
+ }
+ }
+ public override string ToString()
+ {
+ return string.Format("{0},{1}", FontFaceString, _size);
+ }
+
+ public static object Parse(string s)
+ {
+ return (Font)s;
+ }
+ }
+}
+
--- /dev/null
+using System;
+
+namespace go.GLBackend
+{
+ public class FontExtents
+ {
+ double ascent;
+ double descent;
+ double height;
+ double maxXAdvance;
+ double maxYAdvance;
+
+ public double Ascent {
+ get { return ascent; }
+ set { ascent = value; }
+ }
+ public double Descent {
+ get { return descent; }
+ set { descent = value; }
+ }
+ public double Height {
+ get { return height; }
+ set { height = value; }
+ }
+ public double MaxXAdvance {
+ get { return maxXAdvance; }
+ set { maxXAdvance = value; }
+ }
+ public double MaxYAdvance {
+ get { return maxYAdvance; }
+ set { maxYAdvance = value; }
+ }
+
+ public FontExtents ()
+ {
+ }
+ }
+}
+
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.IO;
+using SharpFont;
+using System.Diagnostics;
+using System.Linq;
+using System.Text.RegularExpressions;
+using OpenTK.Graphics.OpenGL;
+
+namespace go.GLBackend
+{
+ public class FontFace
+ {
+ public static int testTexture;
+
+ static List<FontFace> fonts = new List<FontFace>();
+ public Dictionary<uint,Dictionary<uint, glGlyph>> glyphesCache = new Dictionary<uint, Dictionary<uint, glGlyph>>();
+
+ #region CTOR
+ public FontFace ()
+ {
+ }
+ #endregion
+
+ string _name = "droid";
+ string _family;
+ string _fontPath;
+ public FontExtents originalFontExtents;
+
+ FontStyle _style = FontStyle.Normal;
+ FontFlag _flags = FontFlag.None;
+
+ public string Name {
+ get { return _name; }
+ set { _name = value; }
+ }
+ public string Family {
+ get {return _family;}
+ set {_family = value;}
+ }
+ public string FontPath {
+ get { return _fontPath; }
+ set { _fontPath = value; }
+ }
+
+ public FontStyle Style {
+ get { return _style; }
+ set { _style = value; }
+ }
+ public FontFlag Flags {
+ get { return _flags; }
+ set { _flags = value; }
+ }
+
+ public FontSlant Slant {
+ get{
+ if ((Style & FontStyle.Italic) == FontStyle.Italic)
+ return FontSlant.Italic;
+ if ((Style & FontStyle.Oblique) == FontStyle.Oblique)
+ return FontSlant.Oblique;
+ return FontSlant.Normal;
+ }
+ }
+ public FontWeight Wheight {
+ get{ return (Style & FontStyle.Bold) == FontStyle.Bold ? FontWeight.Bold : FontWeight.Normal; }
+ }
+
+ public static FontFace SearchFont(Font font)
+ {
+ FontFace[] tmp = fonts.Where (f =>
+ (string.Compare(f.Name,font.Name,true)==0 && f.Style == font.Style)).ToArray();
+
+ tmp = tmp.Where (f => (f.Flags & font.Flags) == font.Flags).OrderBy(f=>f.Flags).ToArray();
+
+ return tmp.FirstOrDefault();
+ }
+
+ public static void BuildFontsList(string _path)
+ {
+ DirectoryInfo dir = new DirectoryInfo (_path);
+ try
+ {
+ using (Library lib = new Library())
+ {
+ foreach (FileInfo f in dir.GetFiles("*.ttf",SearchOption.AllDirectories)) {
+ try {
+
+ Face face = new Face(lib,f.FullName, 0);
+ FontFace font = new FontFace();
+
+ //TODO:test if font is scalable, if not=>continue
+ font.Family = face.FamilyName;
+ font.FontPath = f.FullName;
+
+ //check if no particularities hidde in family name
+ font.Name = "";
+ string[] styles = face.FamilyName.Split(' ');
+ for (int i = 0; i < styles.Length; i++) {
+ FontFlag fl;
+ FontStyle fs;
+ if (Enum.TryParse<FontFlag> (styles [i], true, out fl))
+ font.Flags |= fl;
+ else if (Enum.TryParse<FontStyle> (styles [i], true, out fs))
+ font.Style |= fs;
+ else//add only unknown word to create shortest possible name
+ font.Name += styles[i] + " ";
+ }
+ font.Name = font.Name.Trim();
+
+ styles = face.StyleName.Split(' ');
+ for (int i = 0; i < styles.Length; i++) {
+ switch (styles[i].ToLowerInvariant()) {
+ case "regular":
+ case "normal":
+ break;
+ case "bold":
+ font.Style |= FontStyle.Bold;
+ break;
+ case "italic":
+ font.Style |= FontStyle.Italic;
+ break;
+ case "oblique":
+ font.Style |= FontStyle.Oblique;
+ break;
+ default:
+ FontFlag fl;
+ if (Enum.TryParse<FontFlag>(styles[i], true, out fl))
+ font.Flags |= fl;
+ break;
+ }
+
+ }
+ fonts.Add(font);
+ face.Dispose();
+ }
+ catch (FreeTypeException ee)
+ { Console.Write(ee.Error.ToString() + ": " + f.FullName); }
+ }
+ }
+ }
+ catch (FreeTypeException e)
+ { Console.Write(e.Error.ToString()); }
+ }
+
+ const int FONT_TEX_SIZE = 1024;
+
+ public void buildGlyphesTextures(uint activeSize, uint startChar, uint endChar){
+ try
+ {
+ using (Library lib = new Library())
+ {
+ Face face = new Face(lib,_fontPath, 0);
+
+ face.SetPixelSizes(0,activeSize);
+
+ //face.SetCharSize(0, 32 * 64, 0, 96);
+
+ originalFontExtents = new FontExtents();
+ originalFontExtents.Ascent = face.Size.Metrics.Ascender >> 6;
+ originalFontExtents.Descent = face.Size.Metrics.Descender >> 6;
+ originalFontExtents.Height = face.Size.Metrics.Height >> 6;
+ originalFontExtents.MaxXAdvance = face.Size.Metrics.MaxAdvance >> 6;
+ originalFontExtents.MaxYAdvance = face.MaxAdvanceHeight >> 6;
+
+ if (!glyphesCache.ContainsKey(activeSize))
+ glyphesCache [activeSize] = new Dictionary<uint, glGlyph>();
+
+ buildTexture(ref face,activeSize,startChar,endChar);
+
+ face.Dispose();
+ }
+ }
+ catch (FreeTypeException e)
+ { Console.Write(e.Error.ToString()); }
+ }
+
+ void setTextureData(int tex, byte[] _buffer)
+ {
+ GL.BindTexture(TextureTarget.Texture2D, tex);
+ GL.TexImage2D(TextureTarget.Texture2D,0,
+ PixelInternalFormat.R8, FONT_TEX_SIZE, FONT_TEX_SIZE,0,
+ OpenTK.Graphics.OpenGL.PixelFormat.Red, PixelType.UnsignedByte,_buffer);
+
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
+ GL.BindTexture(TextureTarget.Texture2D, 0);
+
+ byte[] pixels = new byte[FONT_TEX_SIZE * FONT_TEX_SIZE * 4];
+
+ for (int x = 0; x < FONT_TEX_SIZE; x++)
+ {
+ for (int y = 0; y < FONT_TEX_SIZE; y++)
+ {
+ byte v = _buffer[x + y * FONT_TEX_SIZE];
+
+ pixels[(x + y * FONT_TEX_SIZE) * 4] = v;
+ pixels[(x + y * FONT_TEX_SIZE) * 4 + 1] = v;
+ pixels[(x + y * FONT_TEX_SIZE) * 4 + 2] = v;
+ pixels[(x + y * FONT_TEX_SIZE) * 4 + 3] = 255;
+ }
+ }
+ System.Drawing.Bitmap bmp;
+ unsafe
+ {
+ bmp = new System.Drawing.Bitmap(FONT_TEX_SIZE, FONT_TEX_SIZE, System.Drawing.Imaging.PixelFormat.Format32bppArgb);//, ptr);
+ System.Drawing.Imaging.BitmapData data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, FONT_TEX_SIZE, FONT_TEX_SIZE),
+ System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
+
+ System.Runtime.InteropServices.Marshal.Copy(pixels, 0, data.Scan0, FONT_TEX_SIZE * FONT_TEX_SIZE * 4);
+
+ bmp.UnlockBits(data);
+ }
+
+ bmp.Save(@"/home/jp/fonttex.png");
+
+
+ }
+
+
+ void buildTexture(ref Face face,uint activeSize, uint startChar, uint endChar){
+ int texPage = GL.GenTexture ();
+ byte[] buffer = new byte[FONT_TEX_SIZE*FONT_TEX_SIZE];
+
+ int penX = 0,
+ penY = 0;
+
+ int maxBmpHeight = 0;
+
+ for(uint c=startChar;c<endChar;c++)
+ {
+ uint glyphIndex = face.GetCharIndex((uint)c);
+ if (glyphIndex==0)
+ continue;
+ //face.LoadChar((uint)c, LoadFlags.Render, LoadTarget.Normal);
+ face.LoadGlyph(glyphIndex, LoadFlags.Render, LoadTarget.Normal);
+ testTexture = texPage;
+
+ GlyphSlot slot = face.Glyph;
+ FTBitmap bmp = slot.Bitmap;
+
+ if (penX+bmp.Width > FONT_TEX_SIZE){
+ penX = 0;
+ penY += maxBmpHeight;
+ maxBmpHeight = 0;
+ }
+
+ if (penY+bmp.Rows > FONT_TEX_SIZE)
+ {
+ //glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+ setTextureData (texPage, buffer);
+ texPage = GL.GenTexture ();
+ buffer = new byte[FONT_TEX_SIZE*FONT_TEX_SIZE];
+ penX = 0;
+ penY = 0;
+ maxBmpHeight = 0;
+ }
+
+ Rectangle tmp = new Rectangle (
+ penX,
+ penY,
+ bmp.Width, bmp.Rows);
+
+ for(int y=0; y<bmp.Rows; y++)
+ {
+ for(int x=0; x<bmp.Width; x++)
+ buffer[ penX + x + (penY + y)* FONT_TEX_SIZE ] =
+ bmp.BufferData[x + y * bmp.Width];
+ }
+ glyphesCache [activeSize][c] = new glGlyph()
+ {
+ texId = texPage,
+ texX = (float)penX / FONT_TEX_SIZE,
+ texY = (float)penY / FONT_TEX_SIZE,
+ texWidth = (float)(bmp.Width) / FONT_TEX_SIZE,
+ texHeight = (float)(bmp.Rows) / FONT_TEX_SIZE,
+
+// texCoord = new Rectangle(
+// penX / FONT_TEX_SIZE,
+// penY / FONT_TEX_SIZE,
+// (bmp.Width) / FONT_TEX_SIZE,
+// (bmp.Rows) / FONT_TEX_SIZE),
+ dims = new Size(bmp.Width , bmp.Rows),
+ bmpLeft = slot.BitmapLeft, bmpTop = slot.BitmapTop, advanceX = slot.Advance.X>>6,advanceY = slot.Advance.Y>>6
+ };
+
+ if (bmp.Rows>maxBmpHeight)
+ maxBmpHeight=bmp.Rows;
+
+ penX += bmp.Width;
+ }
+
+ if (penX>0 || penY>0)
+ setTextureData(texPage, buffer);
+ }
+
+ public override string ToString()
+ {
+ string tmp = Name;
+ if (Style != FontStyle.Normal)
+ tmp += "," + Style.ToString ();
+ if (Flags != FontFlag.None)
+ tmp += "," + Flags.ToString ();
+ return tmp;
+ }
+ }
+}
+
--- /dev/null
+using System;
+
+namespace go
+{
+ [Flags]
+ public enum FontFlag
+ {
+ None = 0x00,
+ Sans = 0x01,
+ Serif = 0x02,
+ Mono = 0x04,
+ Condensed = 0x08,
+ Medium = 0x16,
+ Book = 0x32,
+ ExtraLight = 0x64
+ }
+}
+
--- /dev/null
+using System;
+using OpenTK.Graphics.OpenGL;
+
+namespace go.GLBackend
+{
+ public class FontShader : Shader
+ {
+ public FontShader ()
+ {
+ vertSource = @"
+ #version 130
+
+ precision highp float;
+
+ uniform mat4 projection_matrix;
+ uniform mat4 modelview_matrix;
+
+ in vec2 in_position;
+ in vec2 in_tex;
+ out vec2 texCoord;
+
+
+ void main(void)
+ {
+ texCoord = in_tex;
+ gl_Position = projection_matrix * modelview_matrix * vec4(in_position,0, 1);
+ }";
+
+ fragSource = @"
+ #version 130
+ precision highp float;
+
+ uniform vec4 color;
+ uniform sampler2D tex;
+ uniform sampler2D stencil;
+ uniform vec2 resolution;
+
+ in vec2 texCoord;
+ out vec4 out_frag_color;
+
+ vec3
+ energy_distribution( vec4 previous, vec4 current, vec4 next )
+ {
+ float primary = 1.0/3.0;
+ float secondary = 1.0/3.0;
+ float tertiary = 0.0;
+
+ // Energy distribution as explained on:
+ // http://www.grc.com/freeandclear.htm
+ //
+ // .. v..
+ // RGB RGB RGB
+ // previous.g + previous.b + current.r + current.g + current.b
+ //
+ // . .v. .
+ // RGB RGB RGB
+ // previous.b + current.r + current.g + current.b + next.r
+ //
+ // ..v ..
+ // RGB RGB RGB
+ // current.r + current.g + current.b + next.r + next.g
+
+ float r =
+ tertiary * previous.g +
+ secondary * previous.b +
+ primary * current.r +
+ secondary * current.g +
+ tertiary * current.b;
+
+ float g =
+ tertiary * previous.b +
+ secondary * current.r +
+ primary * current.g +
+ secondary * current.b +
+ tertiary * next.r;
+
+ float b =
+ tertiary * current.r +
+ secondary * current.g +
+ primary * current.b +
+ secondary * next.r +
+ tertiary * next.g;
+
+ return vec3(r,g,b);
+ }
+ void main(void)
+ {
+ float a = texture( tex, texCoord).r;
+
+ if (a==0.)
+ discard;
+
+ float x = gl_FragCoord.x / resolution.x;
+ float s = mod(x,x);
+
+ vec4 current = color * texture( tex, texCoord).r;
+ vec4 previous = color * texture( tex, texCoord + vec2(-x,0)).r;
+ vec4 next = color * texture( tex, texCoord + vec2(x,0)).r;
+
+ float r = current.r;
+ float g = current.g;
+ float b = current.b;
+
+ if( s <= 0.333 )
+ {
+ float z = s/0.333;
+ r = mix(current.r, previous.b, z);
+ g = mix(current.g, current.r, z);
+ b = mix(current.b, current.g, z);
+ }
+ else if( s <= 0.666 )
+ {
+ float z = (s-0.33)/0.333;
+ r = mix(previous.b, previous.g, z);
+ g = mix(current.r, previous.b, z);
+ b = mix(current.g, current.r, z);
+ }
+ else if( s < 1.0 )
+ {
+ float z = (s-0.66)/0.334;
+ r = mix(previous.g, previous.r, z);
+ g = mix(previous.b, previous.g, z);
+ b = mix(current.r, previous.b, z);
+ }
+
+
+ out_frag_color = vec4(energy_distribution(previous, current, next),1);
+ }";
+
+ Compile ();
+
+ }
+
+ protected override void BindVertexAttributes ()
+ {
+ base.BindVertexAttributes ();
+ GL.BindAttribLocation(pgmId, 1, "in_tex");
+ }
+ protected override void BindSamplesSlots ()
+ {
+ GL.Uniform1(GL.GetUniformLocation (pgmId, "tex"),0);
+ //GL.Uniform1(GL.GetUniformLocation (pgmId, "stencil"),1);
+ }
+ }
+}
+
--- /dev/null
+using System;
+using OpenTK.Graphics.OpenGL;
+
+namespace go.GLBackend
+{
+ public class FontShader : Shader
+ {
+ protected int coef1Location, coef2Location, coef3Location, coefALocation;
+ public float coef1 {
+ set {GL.Uniform1 (coef1Location, value);}
+ }
+ public float coef2 {
+ set {GL.Uniform1 (coef2Location, value);}
+ }
+ public float coef3 {
+ set {GL.Uniform1 (coef3Location, value);}
+ }
+ public float coefA {
+ set {GL.Uniform1 (coefALocation, value);}
+ }
+ public FontShader ()
+ {
+
+ vertSource = @"
+ #version 130
+
+ precision highp float;
+
+ uniform mat4 projection_matrix;
+ uniform mat4 modelview_matrix;
+
+ in vec2 in_position;
+ in vec2 in_tex;
+ out vec2 texCoord;
+
+
+ void main(void)
+ {
+ texCoord = in_tex;
+ gl_Position = projection_matrix * modelview_matrix * vec4(in_position,0, 1);
+ }";
+
+ fragSource = @"
+ #version 130
+ precision highp float;
+
+ uniform vec4 color;
+ uniform sampler2D tex;
+ uniform sampler2D backTex;
+ uniform sampler2D stencil;
+ uniform vec2 resolution;
+ uniform float coef1;
+ uniform float coef2;
+ uniform float coef3;
+ uniform float coefA;
+
+
+ in vec2 texCoord;
+ out vec4 out_frag_color;
+
+ void main(void)
+ {
+ vec2 uv = gl_FragCoord.xy / resolution;
+ vec2 pix = 1.0 / resolution;
+
+ float c = texture( tex, texCoord).r;
+ vec4 bc = texture( backTex, uv);
+
+ vec4 diff = bc - color;
+
+ if (c==0.)
+ discard;
+
+// if (c > 0.75)
+// out_frag_color = vec4(color.rgb,c);
+// else{
+ float p = texture( tex, texCoord + vec2(-pix.x,0)).r;
+ float n = texture( tex, texCoord + vec2( pix.x,0)).r;
+
+ vec3 current = vec3(0,0,0);
+
+ float a = n - c;
+ current.r += coef1 * a * diff.r;
+ current.g += coef2 * a * diff.g;
+ current.b += coef3 * a * diff.b;
+ //current.a *= coefA * a * diff.a;
+
+ a = p - c;
+ current.r += coef3 * a * diff.r;
+ current.g += coef2 * a * diff.g;
+ current.b += coef1 * a * diff.b;
+ //current.a *= coefA * a * diff.a;
+
+ out_frag_color = vec4(color.rgb+current,c*coefA);
+
+// }
+ }";
+
+ Compile ();
+
+ }
+ protected override void GetUniformLocations ()
+ {
+ base.GetUniformLocations ();
+
+ coef1Location = GL.GetUniformLocation (pgmId, "coef1");
+ coef2Location = GL.GetUniformLocation (pgmId, "coef2");
+ coef3Location = GL.GetUniformLocation (pgmId, "coef3");
+ coefALocation = GL.GetUniformLocation (pgmId, "coefA");
+ }
+ protected override void BindVertexAttributes ()
+ {
+ base.BindVertexAttributes ();
+ GL.BindAttribLocation(pgmId, 1, "in_tex");
+ }
+ protected override void BindSamplesSlots ()
+ {
+ GL.Uniform1(GL.GetUniformLocation (pgmId, "tex"),0);
+ GL.Uniform1(GL.GetUniformLocation (pgmId, "backTex"),1);
+ //GL.Uniform1(GL.GetUniformLocation (pgmId, "stencil"),1);
+ }
+ }
+}
+
--- /dev/null
+//
+// Mono.Cairo.FontSlant.cs
+//
+// Authors:
+// Duncan Mak (duncan@ximian.com)
+// Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace go.GLBackend
+{
+ [Serializable]
+ public enum FontSlant
+ {
+ Normal,
+ Italic,
+ Oblique
+ }
+}
--- /dev/null
+using System;
+
+namespace go
+{
+ [Flags]
+ public enum FontStyle
+ {
+ Normal = 0x00,
+ Bold = 0x01,
+ Italic = 0x02,
+ Oblique = 0x4,
+ Underlined = 0x8
+ }
+}
+
--- /dev/null
+//
+// Mono.Cairo.FontWeight.cs
+//
+// Authors:
+// Duncan Mak (duncan@ximian.com)
+// Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+
+namespace go.GLBackend
+{
+ [Serializable]
+ public enum FontWeight
+ {
+ Normal,
+ Bold,
+ }
+}
--- /dev/null
+//
+// Mono.Cairo.TextExtents.cs
+//
+// Authors:
+// Duncan Mak (duncan@ximian.com)
+// Hisham Mardam Bey (hisham.mardambey@gmail.com)
+//
+// (C) Ximian, Inc. 2003
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Runtime.InteropServices;
+
+namespace go.GLBackend
+{
+ [StructLayout (LayoutKind.Sequential)]
+ public struct TextExtents
+ {
+ double xbearing;
+ double ybearing;
+ double width;
+ double height;
+ double xadvance;
+ double yadvance;
+
+ public double XBearing {
+ get { return xbearing; }
+ set { xbearing = value; }
+ }
+
+ public double YBearing {
+ get { return ybearing; }
+ set { ybearing = value; }
+ }
+
+ public double Width {
+ get { return width; }
+ set { width = value; }
+ }
+
+ public double Height {
+ get { return height; }
+ set { height = value; }
+ }
+
+ public double XAdvance {
+ get { return xadvance; }
+ set { xadvance = value; }
+ }
+
+ public double YAdvance {
+ get { return yadvance; }
+ set { yadvance = value; }
+ }
+
+ public override bool Equals (object obj)
+ {
+ if (obj is TextExtents)
+ return this == (TextExtents)obj;
+ return false;
+ }
+
+ public override int GetHashCode ()
+ {
+ return (int)XBearing ^ (int)YBearing ^ (int)Width ^ (int)Height ^ (int)XAdvance ^ (int)YAdvance;
+ }
+
+ public static bool operator == (TextExtents extents, TextExtents other)
+ {
+ return extents.XBearing == other.XBearing && extents.YBearing == other.YBearing && extents.Width == other.Width && extents.Height == other.Height && extents.XAdvance == other.XAdvance && extents.YAdvance == other.YAdvance;
+ }
+
+ public static bool operator != (TextExtents extents, TextExtents other)
+ {
+ return !(extents == other);
+ }
+ }
+}
--- /dev/null
+using System;
+using SharpFont;
+using OpenTK.Graphics.OpenGL;
+using System.Collections.Generic;
+using System.IO;
+using System.Diagnostics;
+
+namespace go
+{
+ public class glFont
+ {
+ Dictionary<int, glGlyph> glyphs = new Dictionary<int,glGlyph>();
+
+ public static void dumpFontsDirectories(string _path)
+ {
+ List<string> stylesList = new List<string> ();
+ List<string> namesList = new List<string> ();
+ List<string> attribsList = new List<string> ();
+
+ DirectoryInfo dir = new DirectoryInfo (_path);
+ try
+ {
+ using (Library lib = new Library())
+ {
+ Console.WriteLine("FreeType version: " + lib.Version + "\n");
+
+ foreach (FileInfo f in dir.GetFiles("*.ttf",SearchOption.AllDirectories)) {
+ try {
+
+ Face face = new Face(lib,f.FullName, 0);
+
+ Console.Write(System.IO.Path.GetFileNameWithoutExtension(f.Name) + " => ");
+ Console.WriteLine("{0} Faces:{1} Flags:{2}\nStyle:{3} StyleFlags:{4}\n",
+ face.FamilyName,
+ face.FaceCount,
+ face.FaceFlags,
+ face.StyleName,
+ face.StyleFlags);
+ string[] styles = face.StyleName.Split(' ');
+ foreach (string s in styles) {
+ if (stylesList.Contains(s))
+ continue;
+ stylesList.Add(s);
+ }
+
+ string[] names = face.FamilyName.Split(' ');
+ if (!namesList.Contains(names[0]))
+ namesList.Add(names[0]);
+ for (int i = 1; i < names.Length; i++) {
+ if (attribsList.Contains(names[i]))
+ continue;
+ attribsList.Add(names[i]);
+ }
+
+ face.Dispose();
+ }
+ catch (FreeTypeException ee)
+ {
+ Console.Write(ee.Error.ToString() + ": " + f.FullName);
+ }
+ }
+ }
+ }
+ catch (FreeTypeException e)
+ {
+ Console.Write(e.Error.ToString());
+ }
+ Console.Write ("Names => ");
+ foreach (string s in namesList) {
+ Console.Write (s + " ");
+ }
+ Console.Write ("\n\nAttrib => ");
+ foreach (string s in attribsList) {
+ Console.Write (s + " ");
+ }
+
+ Console.Write ("\n\nStyles => ");
+ foreach (string s in stylesList) {
+ Console.Write (s + " ");
+ }
+ }
+
+ public glFont (string _fontPath)
+ {
+
+ }
+
+ }
+}
+
--- /dev/null
+using System;
+
+namespace go
+{
+ public struct glGlyph
+ {
+ public int texId;
+ public Rectangle texCoord;
+ public float texX;
+ public float texY;
+ public float texWidth;
+ public float texHeight;
+ public Size dims;
+ public int bmpLeft;
+ public int bmpTop;
+ public long advanceX;
+ public long advanceY;
+
+
+ }
+}
+
--- /dev/null
+using System;
+using System.Collections.Generic;
+using OpenTK;
+
+namespace go
+{
+ public class Path : List<Vector2>
+ {
+ public bool IsClosed;
+
+ public Path () : base()
+ {
+ }
+ public Path (IEnumerable<Vector2> collection) : base(collection){
+ }
+ }
+}
+
--- /dev/null
+using System;
+using OpenTK.Graphics.OpenGL;
+using System.Diagnostics;
+using OpenTK;
+
+namespace go.GLBackend
+{
+ public class TestShader
+ {
+ string vertexShaderSource = @"
+ #version 130
+
+ //precision highp float;
+
+ uniform float lw;
+ uniform mat4 projection_matrix;
+ uniform mat4 modelview_matrix;
+
+ in vec2 in_position;
+ in vec2 in_tex;
+
+ out vec2 texcoord;
+
+ void main(void)
+ {
+ texcoord = in_tex;
+ gl_Position = projection_matrix * modelview_matrix * vec4(in_position,0, 1);
+ }";
+
+ string fragmentShaderSource = @"
+ #version 130
+
+ //precision highp float;
+ uniform float lw;
+ uniform vec4 color;
+
+ in vec2 texcoord;
+ out vec4 out_frag_color;
+
+ void main(void)
+ {
+// float smoothWidth = 1.0 / lineWidth;
+//
+// if (texcoord.y < smoothWidth)
+// out_frag_color = vec4(color,texcoord.y/smoothWidth);
+// else if (texcoord.y > 1.0 - smoothWidth)
+// out_frag_color = vec4(color,(1.0-texcoord.y)/smoothWidth);
+// else
+// out_frag_color = vec4(color,1.0);
+ out_frag_color = color;
+ }";
+
+ int vertexShaderHandle,
+ fragmentShaderHandle,
+ shaderProgramHandle,
+ modelviewMatrixLocation,
+ projectionMatrixLocation,
+ colorLocation,
+ lineWidthLocation;
+
+ Matrix4 projectionMatrix,
+ modelviewMatrix;
+
+ double lineWidth = 1.0;
+
+ public TestShader ()
+ {
+ vertexShaderHandle = GL.CreateShader(ShaderType.VertexShader);
+ fragmentShaderHandle = GL.CreateShader(ShaderType.FragmentShader);
+
+ GL.ShaderSource(vertexShaderHandle, vertexShaderSource);
+ GL.ShaderSource(fragmentShaderHandle, fragmentShaderSource);
+
+ GL.CompileShader(vertexShaderHandle);
+ GL.CompileShader(fragmentShaderHandle);
+
+ Debug.WriteLine(GL.GetShaderInfoLog(vertexShaderHandle));
+ Debug.WriteLine(GL.GetShaderInfoLog(fragmentShaderHandle));
+
+ // Create program
+ shaderProgramHandle = GL.CreateProgram();
+
+ GL.AttachShader(shaderProgramHandle, vertexShaderHandle);
+ GL.AttachShader(shaderProgramHandle, fragmentShaderHandle);
+
+ GL.BindAttribLocation(shaderProgramHandle, 0, "in_position");
+ GL.BindAttribLocation(shaderProgramHandle, 1, "in_tex");
+
+ GL.LinkProgram(shaderProgramHandle);
+ Debug.WriteLine(GL.GetProgramInfoLog(shaderProgramHandle));
+ GL.UseProgram(shaderProgramHandle);
+
+
+ lineWidthLocation = GL.GetUniformLocation (shaderProgramHandle, "lw");
+ projectionMatrixLocation = GL.GetUniformLocation(shaderProgramHandle, "projection_matrix");
+ modelviewMatrixLocation = GL.GetUniformLocation(shaderProgramHandle, "modelview_matrix");
+ colorLocation = GL.GetUniformLocation (shaderProgramHandle, "color");
+
+ }
+
+ int savedPgm = 0;
+ public virtual void Enable(){
+ GL.GetInteger (GetPName.CurrentProgram, out savedPgm);
+ GL.UseProgram (shaderProgramHandle);
+ }
+ public virtual void Disable(){
+ GL.UseProgram (savedPgm);
+ }
+
+ public Matrix4 ProjectionMatrix{
+ set {
+ projectionMatrix = value;
+ GL.UniformMatrix4(projectionMatrixLocation, false, ref projectionMatrix);
+ }
+ }
+ public Matrix4 ModelViewMatrix {
+ set {
+ modelviewMatrix = value;
+ GL.UniformMatrix4 (modelviewMatrixLocation, false, ref modelviewMatrix);
+ }
+ }
+ public double LineWidth {
+ set {
+ lineWidth = value;
+ GL.Uniform1 (lineWidthLocation, (float)lineWidth);
+ }
+ }
+ public Vector4 Color {
+ set {
+ GL.Uniform4 (colorLocation, value);
+ }
+ }
+ }
+}
+
--- /dev/null
+using System;
+using OpenTK.Graphics.OpenGL;
+
+namespace go.GLBackend
+{
+ [Serializable]
+ public enum Format
+ {
+ Argb32,
+ Rgb24,
+ A8,
+ A1,
+ Rgb16565,
+ ARGB32,
+ RGB24
+ }
+ [Serializable]
+ public enum LineJoin
+ {
+ Miter,
+ Round,
+ Bevel
+ }
+ [Serializable]
+ public enum LineCap
+ {
+ Butt,
+ Round,
+ Square
+ }
+ public class Surface : IDisposable
+ {
+ public static int samples;
+
+ public int texId,
+ width,
+ height;
+ Format format;
+
+ public PixelFormat PixelFormat;
+ public PixelInternalFormat InternalFormat;
+
+ public Surface (int _width, int _height)
+ {
+ format = Format.Argb32;
+ width = _width;
+ height = _height;
+
+ createTexture ();
+ }
+
+ public Surface (Format _format,int _width, int _height)
+ {
+ format = _format;
+ width = _width;
+ height = _height;
+
+ InternalFormat = PixelInternalFormat.Rgba;
+ PixelFormat = PixelFormat.Bgra;
+
+ createTexture ();
+ }
+
+ public Surface CreateSimilar()
+ {
+ return new Surface (format, width, height);
+ }
+
+ void createTexture()
+ {
+ texId = GL.GenTexture();
+ GL.BindTexture(TextureTarget.Texture2D, texId);
+ GL.TexImage2D(TextureTarget.Texture2D,0,
+ PixelInternalFormat.Rgba, width, height,0,PixelFormat.Bgra,PixelType.UnsignedByte,IntPtr.Zero);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Nearest);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Nearest);
+ GL.BindTexture(TextureTarget.Texture2D, 0);
+ }
+
+
+ public void Save(string fileName)
+ {
+ GL.BindTexture(TextureTarget.Texture2D, texId);
+ System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
+ System.Drawing.Imaging.BitmapData data = bmp.LockBits(new System.Drawing.Rectangle(0, 0, width, height),
+ System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
+ GL.GetTexImage(TextureTarget.Texture2D, 0, OpenTK.Graphics.OpenGL.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0);
+ bmp.UnlockBits(data);
+ bmp.RotateFlip (System.Drawing.RotateFlipType.RotateNoneFlipY);
+ bmp.Save(fileName);
+ GL.BindTexture(TextureTarget.Texture2D, 0);
+ }
+
+ #region IDisposable implementation
+ public void Dispose ()
+ {
+ if (GL.IsTexture (texId))
+ GL.DeleteTexture (texId);
+ }
+ #endregion
+ }
+}
+
{\r
GL.GetInteger (GetPName.Viewport, viewport);\r
GL.Viewport (0, 0, ClientRectangle.Width, ClientRectangle.Height);\r
+ bool blend = GL.GetBoolean (GetPName.Blend);\r
+ GL.Enable (EnableCap.Blend);\r
+ GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);\r
shader.Enable ();\r
shader.ProjectionMatrix = projectionMatrix;\r
shader.ModelViewMatrix = modelviewMatrix;\r
shader.Color = new Vector4(1f,1f,1f,1f);\r
- //if (dirtyZone != Rectangle.Empty) {\r
+// //if (dirtyZone != Rectangle.Empty) {\r
GL.ActiveTexture (TextureUnit.Texture0);\r
GL.BindTexture (TextureTarget.Texture2D, texID);\r
GL.TexSubImage2D (TextureTarget.Texture2D, 0,\r
\r
GL.BindTexture(TextureTarget.Texture2D, 0);\r
\r
+ if (!blend)\r
+ GL.Disable (EnableCap.Blend);\r
+\r
shader.Disable ();\r
GL.Viewport (viewport [0], viewport [1], viewport [2], viewport [3]);\r
}\r