184 lines
5.9 KiB
C#
184 lines
5.9 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
|
|
namespace SharpGL
|
|
{
|
|
/// <summary>
|
|
/// A FontBitmap entry contains the details of a font face.
|
|
/// </summary>
|
|
internal class FontBitmapEntry
|
|
{
|
|
public IntPtr HDC
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public IntPtr HRC
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public string FaceName
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public int Height
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public uint ListBase
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public uint ListCount
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This class wraps the functionality of the wglUseFontBitmaps function to
|
|
/// allow straightforward rendering of text.
|
|
/// </summary>
|
|
public class FontBitmaps
|
|
{
|
|
private FontBitmapEntry CreateFontBitmapEntry(OpenGL gl, string faceName, int height)
|
|
{
|
|
// Make the OpenGL instance current.
|
|
gl.MakeCurrent();
|
|
|
|
// Create the font based on the face name.
|
|
var hFont = Win32.CreateFont(height, 0, 0, 0, Win32.FW_DONTCARE, 0, 0, 0, Win32.DEFAULT_CHARSET,
|
|
Win32.OUT_OUTLINE_PRECIS, Win32.CLIP_DEFAULT_PRECIS, Win32.CLEARTYPE_QUALITY, Win32.VARIABLE_PITCH, faceName);
|
|
|
|
// Select the font handle.
|
|
var hOldObject = Win32.SelectObject(gl.RenderContextProvider.DeviceContextHandle, hFont);
|
|
|
|
// Create the list base.
|
|
var listBase = gl.GenLists(1);
|
|
|
|
// Create the font bitmaps.
|
|
bool result = Win32.wglUseFontBitmaps(gl.RenderContextProvider.DeviceContextHandle, 0, 255, listBase);
|
|
|
|
// Reselect the old font.
|
|
Win32.SelectObject(gl.RenderContextProvider.DeviceContextHandle, hOldObject);
|
|
|
|
// Free the font.
|
|
Win32.DeleteObject(hFont);
|
|
|
|
// Create the font bitmap entry.
|
|
var fbe = new FontBitmapEntry()
|
|
{
|
|
HDC = gl.RenderContextProvider.DeviceContextHandle,
|
|
HRC = gl.RenderContextProvider.RenderContextHandle,
|
|
FaceName = faceName,
|
|
Height = height,
|
|
ListBase = listBase,
|
|
ListCount = 255
|
|
};
|
|
|
|
// Add the font bitmap entry to the internal list.
|
|
fontBitmapEntries.Add(fbe);
|
|
|
|
return fbe;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Draws the text.
|
|
/// </summary>
|
|
/// <param name="gl">The gl.</param>
|
|
/// <param name="x">The x.</param>
|
|
/// <param name="y">The y.</param>
|
|
/// <param name="r">The r.</param>
|
|
/// <param name="g">The g.</param>
|
|
/// <param name="b">The b.</param>
|
|
/// <param name="faceName">Name of the face.</param>
|
|
/// <param name="fontSize">Size of the font.</param>
|
|
/// <param name="text">The text.</param>
|
|
public void DrawText(OpenGL gl, int x, int y, float r, float g, float b, string faceName, float fontSize, string text)
|
|
{
|
|
// Get the font size in pixels.
|
|
var fontHeight = (int)(fontSize * (16.0f / 12.0f));
|
|
|
|
// Do we have a font bitmap entry for this OpenGL instance and face name?
|
|
var result = (from fbe in fontBitmapEntries
|
|
where fbe.HDC == gl.RenderContextProvider.DeviceContextHandle
|
|
&& fbe.HRC == gl.RenderContextProvider.RenderContextHandle
|
|
&& String.Compare(fbe.FaceName, faceName, StringComparison.OrdinalIgnoreCase) == 0
|
|
&& fbe.Height == fontHeight
|
|
select fbe).ToList();
|
|
|
|
// Get the FBE or null.
|
|
var fontBitmapEntry = result.FirstOrDefault();
|
|
|
|
// If we don't have the FBE, we must create it.
|
|
if (fontBitmapEntry == null)
|
|
fontBitmapEntry = CreateFontBitmapEntry(gl, faceName, fontHeight);
|
|
|
|
double width = gl.RenderContextProvider.Width;
|
|
double height = gl.RenderContextProvider.Height;
|
|
|
|
// Create the appropriate projection matrix.
|
|
gl.MatrixMode(OpenGL.GL_PROJECTION);
|
|
gl.PushMatrix();
|
|
gl.LoadIdentity();
|
|
|
|
int[] viewport = new int[4];
|
|
gl.GetInteger(OpenGL.GL_VIEWPORT, viewport);
|
|
gl.Ortho(0, width, 0, height, -1, 1);
|
|
|
|
// Create the appropriate modelview matrix.
|
|
gl.MatrixMode(OpenGL.GL_MODELVIEW);
|
|
gl.PushMatrix();
|
|
gl.LoadIdentity();
|
|
gl.Color(r, g, b);
|
|
gl.RasterPos(x, y);
|
|
|
|
gl.PushAttrib(OpenGL.GL_LIST_BIT | OpenGL.GL_CURRENT_BIT |
|
|
OpenGL.GL_ENABLE_BIT | OpenGL.GL_TRANSFORM_BIT);
|
|
gl.Color(r, g, b);
|
|
gl.Disable(OpenGL.GL_LIGHTING);
|
|
gl.Disable(OpenGL.GL_TEXTURE_2D);
|
|
gl.Disable(OpenGL.GL_DEPTH_TEST);
|
|
gl.RasterPos(x, y);
|
|
|
|
// Set the list base.
|
|
gl.ListBase(fontBitmapEntry.ListBase);
|
|
|
|
// Create an array of lists for the glyphs.
|
|
var lists = text.Select(c => (byte) c).ToArray();
|
|
|
|
// Call the lists for the string.
|
|
gl.CallLists(lists.Length, lists);
|
|
gl.Flush();
|
|
|
|
// Reset the list bit.
|
|
gl.PopAttrib();
|
|
|
|
// Pop the modelview.
|
|
gl.PopMatrix();
|
|
|
|
// back to the projection and pop it, then back to the model view.
|
|
gl.MatrixMode(OpenGL.GL_PROJECTION);
|
|
gl.PopMatrix();
|
|
gl.MatrixMode(OpenGL.GL_MODELVIEW);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cache of font bitmap enties.
|
|
/// </summary>
|
|
private readonly List<FontBitmapEntry> fontBitmapEntries = new List<FontBitmapEntry>();
|
|
}
|
|
}
|