⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 d3dfont.cs

📁 Beginning C# Game Programming 的源代码
💻 CS
📖 第 1 页 / 共 2 页
字号:
//-----------------------------------------------------------------------------
// File: D3DFont.cs
//
// Desc: Shortcut functions for using DX objects
//
// Copyright (c) Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
using System;
using System.Drawing;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using Direct3D = Microsoft.DirectX.Direct3D;




/// <summary>
/// A generic font class 
/// </summary>
public class GraphicsFont {
	public const int MaxNumfontVertices = 50*6;
  
	// Font rendering flags
	[System.Flags]
		public enum RenderFlags {
		Centered = 0x0001,
		TwoSided = 0x0002, 
		Filtered = 0x0004,
	}
	private System.Drawing.Font systemFont;

	private bool isZEnable = false;
	public bool ZBufferEnable { get { return isZEnable; } set { isZEnable = value; } }
	string ourFontName; // Font properties
	int ourFontHeight;

	private Direct3D.Device device;
	private TextureStateManager textureState0;
	private TextureStateManager textureState1;
	private SamplerStateManager samplerState0;
	private RenderStateManager renderState;
	private Direct3D.Texture fontTexture;
	private Direct3D.VertexBuffer vertexBuffer;
	private CustomVertex.TransformedColoredTextured[] fontVertices = new CustomVertex.TransformedColoredTextured[MaxNumfontVertices];

	private int textureWidth; // Texture dimensions
	private int textureHeight;
	private float textureScale;
	private int spacingPerChar;
	private float[,] textureCoords = new float[128-32,4];

	// Stateblocks for setting and restoring render states
	private StateBlock savedStateBlock;
	private StateBlock drawTextStateBlock;




	/// <summary>
	/// Create a new font object
	/// </summary>
	/// <param name="f">The font to use</param>
	public GraphicsFont(System.Drawing.Font f) {
		ourFontName = f.Name;
		ourFontHeight = (int)f.Size;
		systemFont = f;
	}

    
    
	/// <summary>
	/// Create a new font object
	/// </summary>
	public GraphicsFont(string fontName) : this(fontName, FontStyle.Regular, 12) {
	}


    
    
	/// <summary>
	/// Create a new font object
	/// </summary>
	public GraphicsFont(string fontName, FontStyle style) : this(fontName, style, 12) {
	}




	/// <summary>
	/// Create a new font object
	/// </summary>
	/// <param name="fontName">The name of the font</param>
	/// <param name="style">The style</param>
	/// <param name="size">Size of the font</param>
	public GraphicsFont(string fontName, FontStyle style, int size) {
		ourFontName = fontName;
		ourFontHeight = size;
		systemFont = new System.Drawing.Font(fontName, ourFontHeight, style);
	}




	/// <summary>
	/// Attempt to draw the systemFont alphabet onto the provided texture
	/// graphics.
	/// </summary>
	/// <param name="g"></param>Graphics object on which to draw and measure the letters</param>
	/// <param name="measureOnly">If set, the method will test to see if the alphabet will fit without actually drawing</param>
	public void PaintAlphabet(Graphics g, bool measureOnly) {
		string str;
		float x = 0;
		float y = 0;
		Point p = new Point(0, 0);
		Size size = new Size(0,0);
            
		// Calculate the spacing between characters based on line height
		size = g.MeasureString(" ", systemFont).ToSize();
		x = spacingPerChar = (int) Math.Ceiling(size.Height * 0.3);

		for (char c = (char)32; c < (char)127; c++) {
			str = c.ToString();
			// We need to do some things here to get the right sizes.  The default implemententation of MeasureString
			// will return a resolution independant size.  For our height, this is what we want.  However, for our width, we 
			// want a resolution dependant size.
			Size resSize = g.MeasureString(str, systemFont).ToSize();
			size.Height = resSize.Height + 1;

			// Now the Resolution independent width
			if (c != ' ') { // We need the special case here because a space has a 0 width in GenericTypoGraphic stringformats
				resSize = g.MeasureString(str, systemFont, p, StringFormat.GenericTypographic).ToSize();
				size.Width = resSize.Width;
			}
			else
				size.Width = resSize.Width;

			if ((x + size.Width + spacingPerChar) > textureWidth) {
				x = spacingPerChar;
				y += size.Height;
			}

			// Make sure we have room for the current character
			if ((y + size.Height) > textureHeight)
				throw new System.InvalidOperationException("Texture too small for alphabet");
                
			if (!measureOnly) {
				if (c != ' ') // We need the special case here because a space has a 0 width in GenericTypoGraphic stringformats
					g.DrawString(str, systemFont, Brushes.White, new Point((int)x, (int)y), StringFormat.GenericTypographic);
				else
					g.DrawString(str, systemFont, Brushes.White, new Point((int)x, (int)y));
				textureCoords[c-32,0] = ((float) (x + 0           - spacingPerChar)) / textureWidth;
				textureCoords[c-32,1] = ((float) (y + 0           + 0)) / textureHeight;
				textureCoords[c-32,2] = ((float) (x + size.Width  + spacingPerChar)) / textureWidth;
				textureCoords[c-32,3] = ((float) (y + size.Height + 0)) / textureHeight;
			}

			x += size.Width + (2 * spacingPerChar);
		}

	}




	/// <summary>
	/// Initialize the device objects
	/// </summary>
	/// <param name="dev">The grpahics device used to initialize</param>
	public void InitializeDeviceObjects(Device dev) {
		if (dev != null) {
			// Set up our events
			dev.DeviceReset += new System.EventHandler(this.RestoreDeviceObjects);
		}

		// Keep a local copy of the device
		device = dev;
		textureState0 = device.TextureState[0];
		textureState1 = device.TextureState[1];
		samplerState0 = device.SamplerState[0];
		renderState = device.RenderState;

		// Create a bitmap on which to measure the alphabet
		Bitmap bmp = new Bitmap(1, 1, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
		Graphics g = Graphics.FromImage(bmp);
		g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
		g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
		g.TextContrast = 0;
       
		// Establish the font and texture size
		textureScale  = 1.0f; // Draw fonts into texture without scaling

		// Calculate the dimensions for the smallest power-of-two texture which
		// can hold all the printable characters
		textureWidth = textureHeight = 128;
		for (;;) {
			try {
				// Measure the alphabet
				PaintAlphabet(g, true);
			}
			catch (System.InvalidOperationException) {
				// Scale up the texture size and try again
				textureWidth *= 2;
				textureHeight *= 2;
				continue;
			}

			break;
		}

		// If requested texture is too big, use a smaller texture and smaller font,
		// and scale up when rendering.
		Direct3D.Caps d3dCaps = device.DeviceCaps;

		// If the needed texture is too large for the video card...
		if (textureWidth > d3dCaps.MaxTextureWidth) {
			// Scale the font size down to fit on the largest possible texture
			textureScale = (float)d3dCaps.MaxTextureWidth / (float)textureWidth;
			textureWidth = textureHeight = d3dCaps.MaxTextureWidth;

			for(;;) {
				// Create a new, smaller font
				ourFontHeight = (int) Math.Floor(ourFontHeight * textureScale);      
				systemFont = new System.Drawing.Font(systemFont.Name, ourFontHeight, systemFont.Style);
                
				try {
					// Measure the alphabet
					PaintAlphabet(g, true);
				}
				catch (System.InvalidOperationException) {
					// If that still doesn't fit, scale down again and continue
					textureScale *= 0.9F;
					continue;
				}

				break;
			}
		}

		// Release the bitmap used for measuring and create one for drawing
		bmp.Dispose();
		bmp = new Bitmap(textureWidth, textureHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
		g = Graphics.FromImage(bmp);
		g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
		g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;
		g.TextContrast = 0;

		// Draw the alphabet
		PaintAlphabet(g, false);

		// Create a new texture for the font from the bitmap we just created
		fontTexture = Texture.FromBitmap(device, bmp, 0, Pool.Managed);
		RestoreDeviceObjects(null, null);
	}




	/// <summary>
	/// Restore the font after a device has been reset
	/// </summary>
	public void RestoreDeviceObjects(object sender, EventArgs e) {
		vertexBuffer = new VertexBuffer(typeof(CustomVertex.TransformedColoredTextured), MaxNumfontVertices,
			device, Usage.WriteOnly | Usage.Dynamic, 0, Pool.Default);

		Surface surf = device.GetRenderTarget( 0 );
		bool bSupportsAlphaBlend = Manager.CheckDeviceFormat(device.DeviceCaps.AdapterOrdinal, 
			device.DeviceCaps.DeviceType, device.DisplayMode.Format, 
			Usage.RenderTarget | Usage.QueryPostPixelShaderBlending, ResourceType.Surface, 
			surf.Description.Format );

		// Create the state blocks for rendering text
		for (int which=0; which < 2; which++) {
			device.BeginStateBlock();
			device.SetTexture(0, fontTexture);

			if (isZEnable)
				renderState.ZBufferEnable = true;
			else
				renderState.ZBufferEnable = false;

			if( bSupportsAlphaBlend ) {
				renderState.AlphaBlendEnable = true;
				renderState.SourceBlend = Blend.SourceAlpha;
				renderState.DestinationBlend = Blend.InvSourceAlpha;
			}
			else {
				renderState.AlphaBlendEnable = false;
			}
			renderState.AlphaTestEnable = true;
			renderState.ReferenceAlpha = 0x08;
			renderState.AlphaFunction = Compare.GreaterEqual;
			renderState.FillMode = FillMode.Solid;
			renderState.CullMode = Cull.CounterClockwise;
			renderState.StencilEnable = false;
			renderState.Clipping = true;
			device.ClipPlanes.DisableAll();
			renderState.VertexBlend = VertexBlend.Disable;
			renderState.IndexedVertexBlendEnable = false;
			renderState.FogEnable = false;
			renderState.ColorWriteEnable = ColorWriteEnable.RedGreenBlueAlpha;
			textureState0.ColorOperation = TextureOperation.Modulate;
			textureState0.ColorArgument1 = TextureArgument.TextureColor;
			textureState0.ColorArgument2 = TextureArgument.Diffuse;
			textureState0.AlphaOperation = TextureOperation.Modulate;
			textureState0.AlphaArgument1 = TextureArgument.TextureColor;
			textureState0.AlphaArgument2 = TextureArgument.Diffuse;
			textureState0.TextureCoordinateIndex = 0;
			textureState0.TextureTransform = TextureTransform.Disable; // REVIEW
			textureState1.ColorOperation = TextureOperation.Disable;
			textureState1.AlphaOperation = TextureOperation.Disable;
			samplerState0.MinFilter = TextureFilter.Point;
			samplerState0.MagFilter = TextureFilter.Point;
			samplerState0.MipFilter = TextureFilter.None;

			if (which==0)
				savedStateBlock = device.EndStateBlock();
			else
				drawTextStateBlock = device.EndStateBlock();
		}
	}




	/// <summary>
	/// Draw some text on the screen
	/// </summary>
	public void DrawText(float xpos, float ypos, Color color, string text) {
		DrawText(xpos, ypos, color, text, RenderFlags.Filtered);
	}



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -