/// <summary> /// Calculates the space for the legend /// </summary> /// <param name="pane">The pane.</param> /// <param name="rect">The rect.</param> public void CalcRect(PaneBase pane, ref GLRectangleF rect) { if (pane is GraphPane) { int numLines = _legendEntries.Count / _nEntriesVert; if (numLines * _nEntriesVert != _legendEntries.Count) { numLines += 1; } int LegendHeight = (int)(_lineHeight * numLines); _rect.Y = pane.Rect.Y + _margin.Bottom; _rect.X = pane.Rect.X + _margin.Left; _rect.Height = LegendHeight; _rect.Width = pane.Rect.Width - _margin.Left - _margin.Right; _innerRect.Height = _rect.Height * 0.95f; _innerRect.Width = _rect.Width * 0.98f; _innerRect.X = _rect.X + (_rect.Width - _innerRect.Width) / 2; _innerRect.Y = _rect.Y + (_rect.Height - _innerRect.Height) / 2; rect.Y += LegendHeight + _margin.Top + _margin.Bottom; rect.Height -= LegendHeight + _margin.Top + _margin.Bottom; _entrySpaceX = (int)((_innerRect.Width - (_nEntriesVert - 1) * _entryGapX) / _nEntriesVert); _colorLineLen = (int)(0.18f * _entrySpaceX); _textLen = (int)(_entrySpaceX * 0.8f); } }
/// <summary> /// Initializes a new instance of the <see cref="Legend"/> class. /// </summary> /// <param name="textInstance">The text instance.</param> public Legend(TextInstance textInstance) { _legendEntries = new List <LegendEntry>(); _border = new GL_Border(Color.Black, textInstance.Shaders); _textInstance = textInstance; _linesShader = textInstance.Shaders.LineShader; _rect = new GLRectangleF(0, 0, 0, 0); _innerRect = new GLRectangleF(0, 0, 0, 0); _entryGapX = 2; _nEntriesVert = 5; _margin = new Margin(); _margin.Left = 10; _margin.Right = 10; _margin.Top = 2; _margin.Bottom = 5; _lineHeight = textInstance.FontSize * 0.8; _VBOLine = GL.GenBuffer();//set up OpenGL by generating buffers and using the shader _VAOLine = GL.GenVertexArray(); _linesShader.Use(); GL.BindVertexArray(_VAOLine);//setting up VAO states and binding the VBO GL.EnableVertexAttribArray(_linesShader.VertexLocation); GL.BindBuffer(BufferTarget.ArrayBuffer, _VBOLine); _mat = Matrix4.Identity; GL.UniformMatrix4(_linesShader.MatrixLocation, false, ref _mat); GL.VertexAttribPointer(_linesShader.VertexLocation, 2, VertexAttribPointerType.Float, false, 2 * sizeof(float), 0); GL.BindVertexArray(0); _linesShader.StopUse(); }
/// <summary> /// Translate a point to the x/y-coordinate system of the viewport /// </summary> /// <param name="point">The point.</param> /// <param name="rect">The rect.</param> /// <returns>Gets the transformed point in the coordinatesystem of the viewport which ranges -1...1 in x and y</returns> private PointF PointToViewport(PointF point, GLRectangleF rect) { PointF ViewportPoint = new PointF { X = 2 * (point.X - rect.X) / rect.Width - 1, Y = 2 * (point.Y - rect.Y) / rect.Height - 1 }; return(ViewportPoint); }
/// <summary> /// Resizes the Rectangle, setting the posset of the first <see cref="LegendEntry"/> /// so that the legend gets resized after this happens /// </summary> /// <param name="rect">The rect.</param> public virtual void ReSize(GLRectangleF rect) { _rect = rect; try { _legend[0].PosSet = false; } catch { } }
/// <summary> /// Calculates the client rect. /// </summary> /// <returns>a rectangle reduced by the <see cref="Margin"/> values</returns> public GLRectangleF CalcClientRect() { GLRectangleF innerRect = new GLRectangleF( _rect.X + _margin.Left, _rect.Y + _margin.Bottom, _rect.Width - (_margin.Left + _margin.Right), _rect.Height - (_margin.Top + _margin.Bottom)); this._legend.CalcRect(this, ref innerRect); return(innerRect); }
/// <summary> /// Draws the Border to the specified rectangle /// </summary> /// <param name="rect">The rect.</param> public void Draw(GLRectangleF rect) { GL.Viewport((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height); _shaders.LineShader.Use(); GL.BindVertexArray(_VAO); GL.Uniform4(_shaders.LineShader.ColorLocation, _color); GL.UniformMatrix4(_shaders.LineShader.MatrixLocation, false, ref _mat); GL.DrawArrays(PrimitiveType.LineLoop, 0, _border.Length / 2); GL.BindVertexArray(0); _shaders.LineShader.StopUse(); }
/// <summary> /// Initializes a new instance of the <see cref="PaneBase"/> class. /// </summary> /// <param name="paneRect">The pane rect.</param> /// <param name="textInstance">The text instance.</param> public PaneBase(RectangleF paneRect, TextInstance textInstance) { _rect = new GLRectangleF(0, 0, 0, 0); _rect.X = (int)paneRect.X; _rect.Height = (int)paneRect.Height; _rect.Width = (int)paneRect.Width; _rect.Y = (int)paneRect.Bottom; _margin = new Margin(); _glBorder = new GL_Border(Color.Black, textInstance.Shaders); _legend = new Legend(textInstance); }
/// <summary> /// Calculates the chart rect. /// </summary> /// <returns>The rectangle where the <see cref="CurveList"/> can be drawn. /// It gets smaller the more axes and the more Legend entries exist.</returns> public GLRectangleF CalcChartRect() { // chart rect starts out at the full pane rect less the margins // and less space for the Pane title int minSpaceL = 0; GLRectangleF clientRect = this.CalcClientRect(); _xAxis.CalcSpace(out int minSpaceB); foreach (Axis axis in _yAxisList) { int tmp = axis.CalcSpace(out int fixedSpace); minSpaceL += fixedSpace; } clientRect.X += minSpaceL; clientRect.Y += minSpaceB; clientRect.Height -= minSpaceB; clientRect.Width -= minSpaceL; return(clientRect); }
/// <summary> /// Draws the pane frame. /// </summary> public void DrawPaneFrame() { GLRectangleF rect = new GLRectangleF(_rect.X, _rect.Y, _rect.Width - 1, _rect.Height - 1); _glBorder.Draw(rect); }
/// <summary> /// Generates the font image, the VAO and the <see cref="CharSheet"/> storing all <see cref="Character"/> /// </summary> /// <param name="rect">The rect.</param> public void GenerateFontImage(GLRectangleF rect) { int bitmapWidth = _glyphsPerLine * _glyphWidth; //calculate bitmap dimensions int bitmapHeight = _glyphLineCount * _glyphHeight; //generating the bitmap and setting it up first using (Bitmap bitmap = new Bitmap(bitmapWidth, bitmapHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb)) { Font font; font = new Font(new FontFamily(_fontName), _fontSize, FontStyle.Regular, GraphicsUnit.Pixel); using (var g = Graphics.FromImage(bitmap)) { if (_bitmapFont) { g.SmoothingMode = SmoothingMode.None; g.TextRenderingHint = TextRenderingHint.SingleBitPerPixel; } else { g.SmoothingMode = SmoothingMode.HighQuality; g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit; } //draw each character onto the bitmap for (int p = 0; p < _glyphLineCount; p++) { for (int n = 0; n < _glyphsPerLine; n++) { char c = (char)(n + p * _glyphsPerLine); g.DrawString(c.ToString(), font, Brushes.Black, n * _glyphWidth + _atlasOffsetX, p * _glyphHeight + _atlasOffsetY); } } } bitmap.Save(_fontBitmapFilename);//save the bitmap _textureWidth = bitmap.Width; _textureHeight = bitmap.Height; } _shaders.TextShader.Use(); //bind the bitmap to an OpenGL Texture _fontTextureID = GL.GenTexture(); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, _fontTextureID); using (var image = new Bitmap(_fontBitmapFilename)) {//load the bitmap into OpenGL var data = image.LockBits( new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb); GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Rgba, image.Width, image.Height, 0, OpenTK.Graphics.OpenGL4.PixelFormat.Bgra, PixelType.UnsignedByte, data.Scan0); } //set up the filters for the bitmap GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat); //generate the VAO and bind it _VAO = GL.GenVertexArray(); GL.BindVertexArray(_VAO); //enable the vertex attribute arrays, very important otherwise no vertix can be loaded into OpenGL GL.EnableVertexAttribArray(_shaders.TextShader.TexCoordLocation); GL.EnableVertexAttribArray(_shaders.TextShader.VertexLocation); //generate the CharSheet from the information about the bitmap _charSheet = new CharSheet(_glyphLineCount, _glyphsPerLine, _glyphHeight, _glyphWidth, _textureWidth, _textureHeight, rect); //set the attribpointers to tell the Shader how the Vertices will be passed. GL.VertexAttribPointer(_shaders.TextShader.VertexLocation, 2, VertexAttribPointerType.Float, false, 4 * sizeof(float), 0); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, _fontTextureID); GL.VertexAttribPointer(_shaders.TextShader.TexCoordLocation, 2, VertexAttribPointerType.Float, false, 4 * sizeof(float), 2 * sizeof(float)); GL.BindVertexArray(0); _shaders.TextShader.StopUse(); GL.Enable(EnableCap.Blend);//enable blending for the bitmap GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); }
public CharSheet(int GlyphLineCount, int GlyphsPerLine, int GlyphHeight, int GlyphWidth, int TextureWidth, int TextureHeight, GLRectangleF rect) { for (int p = 0; p < GlyphLineCount; p++) { for (int n = 0; n < GlyphsPerLine; n++) { Character character = new Character((char)(n + p * GlyphsPerLine), GlyphHeight, GlyphWidth, TextureWidth, TextureHeight, GlyphsPerLine, rect); this.Add(character); } } }
/// <summary> /// Initializes a new instance of the <see cref="Character"/> class. /// It combines the Coordinates of the bitmap containing the font /// with the Coordinates of the screen /// </summary> /// <param name="character">The character.</param> /// <param name="GlyphHeight">Height of the glyph.</param> /// <param name="GlyphWidth">Width of the glyph.</param> /// <param name="TextureWidth">Width of the texture.</param> /// <param name="TextureHeight">Height of the texture.</param> /// <param name="GlyphsPerLine">The glyphs per line.</param> /// <param name="rect">The rect.</param> public Character(char character, int GlyphHeight, int GlyphWidth, int TextureWidth, int TextureHeight, int GlyphsPerLine, GLRectangleF rect) { _char = character; //store the char for referencing float u_step = (float)GlyphWidth / (float)TextureWidth; //step sizes for stepping throught the bitmap float v_step = (float)GlyphHeight / (float)TextureHeight; float u = (float)(character % GlyphsPerLine) * u_step; //Starting positions of the character inside the bitmap float v = (float)(character / GlyphsPerLine) * v_step; float x = -GlyphWidth / 2, y = 0; //Screen coordinates, specifying the bottom mit point of the glyph _vertices = new float[] { //setting the vertices x / rect.Width, y / rect.Height, u, v, -x / rect.Width, y / rect.Height, u + u_step, v, -x / rect.Width, -GlyphHeight / rect.Height, u + u_step, v + v_step, x / rect.Width, y / rect.Height, u, v, -x / rect.Width, -GlyphHeight / rect.Height, u + u_step, v + v_step, x / rect.Width, -GlyphHeight / rect.Height, u, v + v_step }; _VBO = GL.GenBuffer();//generate the VBO, binding it and putting the Vertices inside. GL.BindBuffer(BufferTarget.ArrayBuffer, _VBO); GL.BufferData <float>(BufferTarget.ArrayBuffer, (IntPtr)(sizeof(float) * _vertices.Length), _vertices, BufferUsageHint.DynamicDraw); }