PageRenderTime 58ms CodeModel.GetById 2ms app.highlight 49ms RepoModel.GetById 1ms app.codeStats 1ms

/Rendering/BasicTests/FontTests.cs

Relevant Search: With Applications for Solr and Elasticsearch

For more in depth reading about search, ranking and generally everything you could ever want to know about how lucene, elasticsearch or solr work under the hood I highly suggest this book. Easily one of the most interesting technical books I have read in a long time. If you are tasked with solving search relevance problems even if not in Solr or Elasticsearch it should be your first reference. Amazon Affiliate Link
#
C# | 737 lines | 522 code | 78 blank | 137 comment | 37 complexity | 4e55233fee16df54ded4851700d36296 MD5 | raw file
  1using System;
  2using System.Collections.Generic;
  3using System.Diagnostics;
  4using System.Text;
  5using Delta.ContentSystem.Rendering;
  6using Delta.Engine;
  7using Delta.InputSystem;
  8using Delta.InputSystem.Devices;
  9using Delta.Rendering.Basics.Drawing;
 10using Delta.Rendering.Basics.Fonts;
 11using Delta.Rendering.Basics.Materials;
 12using Delta.Rendering.Enums;
 13using Delta.Utilities;
 14using Delta.Utilities.Datatypes;
 15using Delta.Utilities.Datatypes.Advanced;
 16using Delta.Utilities.Graphics;
 17using Delta.Utilities.Helpers;
 18using NUnit.Framework;
 19
 20namespace Delta.Rendering.BasicTests
 21{
 22	/// <summary>
 23	/// All unit tests for the Delta.Rendering.Fonts module.
 24	/// <para />
 25	/// Reference of "famous" test sentences for bitmap fonts:
 26	/// http://forums.appleinsider.com/archive/index.php/t-57707.html
 27	/// </summary>
 28	public class FontTests
 29	{
 30		#region DrawSimpleText (Static)
 31		/// <summary>
 32		/// Draw simple text in the center of the screen. Also used as a font
 33		/// rendering performance test. In both debug and release mode and even
 34		/// with attached profiler we can reach the max. fps here (10k on my
 35		/// system in OpenTK, Sandy Bridge 4Ghz, GeForce 480). It gets interesting
 36		/// when disabling swap buffer, clear and geometry rendering, then the fps
 37		/// goes up to 1.5 million in release mode and 600 000 fps in debug mode :)
 38		/// </summary>
 39		[Test]
 40		public static void DrawSimpleText()
 41		{
 42			Application.Start(delegate
 43			{
 44				Font.Default.Draw("Hi there",
 45					Rectangle.FromCenter(Point.Half, Size.Half));
 46			});
 47		}
 48		#endregion
 49
 50		#region TestTextAlignment (Static)
 51		/// <summary>
 52		/// TestTextAlignment with some helper lines, boxes and font map to see
 53		/// if everything is pixel aligned correctly.
 54		/// </summary>
 55		[Test]
 56		public static void TestTextAlignment()
 57		{
 58			Material2D fontMaterial = new Material2D("Verdana_9_16");
 59
 60			Application.Start(delegate
 61			{
 62				Line.Draw(Point.Zero, Point.One, Color.Green);
 63				Material2D.Default.Draw(ScreenSpace.ToQuadraticSpace(
 64					new Rectangle(0, 0, 10, 10)));
 65				Font.Default.Draw(
 66					Application.Window.ViewportPixelWidth + "," +
 67					Application.Window.ViewportPixelHeight, ScreenSpace.DrawArea);
 68
 69				fontMaterial.Draw(ScreenSpace.ToQuadraticSpace(
 70					new Rectangle(10, 70, 128, 128)));//test: 113 0 7 12
 71			});
 72		}
 73		#endregion
 74
 75		#region DrawSingleLineTextCentered (Static)
 76		/// <summary>
 77		/// Draw single line text centered
 78		/// </summary>
 79		[Test]
 80		public static void DrawSingleLineTextCentered()
 81		{
 82			Application.Start(delegate
 83			{
 84				Font.Default.Draw("Jackdaws love my big sphinx of quartz.",
 85					Rectangle.FromCenter(0.5f, 0.5f, 0.2f, 0.2f));
 86			});
 87		}
 88		#endregion
 89
 90		#region DrawSingleLineTextTopLeft (Static)
 91		/// <summary>
 92		/// Draw single line text in the top left corner
 93		/// </summary>
 94		[Test]
 95		public static void DrawSingleLineTextTopLeft()
 96		{
 97			Application.Start(delegate
 98			{
 99				Font.DrawTopLeftInformation("Jackdaws love my big sphinx of quartz.");
100			});
101		}
102		#endregion
103
104		#region DrawMultiLineText (Static)
105		/// <summary>
106		/// Draw multi line text
107		/// </summary>
108		[Test]
109		public static void DrawMultiLineText()
110		{
111			Font infoFont = new Font(Font.Default,
112				HorizontalAlignment.Left, VerticalAlignment.Top);
113			Application.Start(delegate
114			{
115				infoFont.Draw(
116					"Jackdaws love my big sphinx of quartz.\n" +
117					"But another idiom is:\r\n" +
118					"Six big juicy steaks sizzled in a pan as five workmen left the" +
119					" quarry.\r" +
120					":)",
121					new Rectangle(0.5f, 0.5f, 0.2f, infoFont.LineHeight));
122			});
123		}
124		#endregion
125
126		#region MeasureSingleLineText (Static)
127		/// <summary>
128		/// Measure single line text
129		/// </summary>
130		[Test]
131		public static void MeasureSingleLineText()
132		{
133			const string Text = "Jackdaws love my big sphinx of quartz.";
134			Font infoFont = new Font(Font.Default,
135				HorizontalAlignment.Left, VerticalAlignment.Top);
136			Point textStartPosition = Point.Half;
137
138			Application.Start(delegate
139			{
140				// Measure the text
141				Size textSize = infoFont.Measure(Text);
142				// and draw the measured text size
143				Rect.DrawOutline(new Rectangle(textStartPosition, textSize),
144					Color.Red);
145
146				// and additionally the original text to check if the computed text
147				// fits with the drawn text too
148				infoFont.Draw(Text, new Rectangle(textStartPosition,
149					new Size(0.2f, infoFont.LineHeight)));
150			});
151		}
152		#endregion
153
154		#region MeasureMultiLineText (Static)
155		/// <summary>
156		/// Measure multi line text
157		/// </summary>
158		[Test]
159		public static void MeasureMultiLineText()
160		{
161			string text =
162				"Jackdaws love my big sphinx of quartz.\n" +
163				"But another idiom is:\r\n" +
164				"Six big juicy steaks sizzled in a pan as five workmen left the" +
165				" quarry.\r" +
166				":)";
167
168			Font infoFont = new Font(Font.Default,
169				HorizontalAlignment.Left, VerticalAlignment.Top);
170
171			Point textStartPos = new Point(0.2f, 0.4f);
172			Application.Start(delegate
173			{
174				// Measure the text
175				Size textSize = infoFont.Measure(text);
176				// and draw the measured text size
177				Rect.DrawOutline(new Rectangle(textStartPos, textSize), Color.Red);
178
179				// and additionally the original text to prove if the computed text
180				// fits with the drawn text too
181				Size availableTextSize = textSize * 1.25f;
182				infoFont.Draw(text, new Rectangle(textStartPos, availableTextSize));
183				// and draw also the available text size
184				Rect.DrawOutline(new Rectangle(textStartPos, availableTextSize),
185					Color.Green);
186			});
187		}
188		#endregion
189
190		#region MeasureTab (Static)
191		/// <summary>
192		/// Measure tab
193		/// </summary>
194		[Test]
195		public static void MeasureTab()
196		{
197			Font infoFont = new Font(Font.Default, 
198				HorizontalAlignment.Left, VerticalAlignment.Top);
199
200			Point textStartPosition = Point.Half;
201			Application.Start(delegate
202			{
203				// Measure the tab
204				Size numberSize = infoFont.Measure("0");
205				Size tabSize = infoFont.Measure("\t");
206				// and draw the measured text size
207				Rectangle tabRectangle = new Rectangle(textStartPosition, tabSize);
208				tabRectangle.X += numberSize.Width;
209				Rect.DrawOutline(tabRectangle, Color.Red);
210
211				// and addionally the tab + some text for better visualization and
212				// comparing it
213				infoFont.Draw("0\t123456789", new Rectangle(textStartPosition,
214					new Size(0.2f, infoFont.LineHeight)));
215				// wit normal spaces
216				infoFont.Draw("0 1 2 3 456789", new Rectangle(textStartPosition.X,
217					textStartPosition.Y + infoFont.LineHeight,
218					0.2f, infoFont.LineHeight));
219			});
220		}
221		#endregion
222
223		#region DrawSingleLineTextAligned (Static)
224		/// <summary>
225		/// Draw single line text aligned
226		/// </summary>
227		[Test]
228		public static void DrawSingleLineTextAligned()
229		{
230			// Get the number of available horizontal
231			int horizontalAlignmentModes =
232				EnumHelper.GetCount<HorizontalAlignment>();
233			// and vertical alignment modes
234			int verticalAlignmentModes =
235				EnumHelper.GetCount<VerticalAlignment>();
236
237			// Create fonts with every horizontal and vertical alignment mode
238			Font[,] fonts =
239				new Font[horizontalAlignmentModes, verticalAlignmentModes];
240			for (int hModeId = 0; hModeId < horizontalAlignmentModes; hModeId++)
241			{
242				for (int vModeId = 0; vModeId < verticalAlignmentModes; vModeId++)
243				{
244					fonts[hModeId, vModeId] = new Font(Font.Default,
245						(HorizontalAlignment)hModeId, (VerticalAlignment)vModeId);
246				}
247			}
248
249			Application.Start(delegate
250			{
251				// Show a text with every possible horizontal and vertical alignment
252				for (int hModeId = 0; hModeId < horizontalAlignmentModes; hModeId++)
253				{
254					for (int vModeId = 0; vModeId < verticalAlignmentModes; vModeId++)
255					{
256						// While the code for all fonts is the same, the actual rendering
257						// will appear at different locations on the screen depending on
258						// the current alignment combination.
259						Font font = fonts[hModeId, vModeId];
260						font.Draw(
261							"Text at '" + font.HorizontalAlignment + " " +
262							font.VerticalAlignment + "'", ScreenSpace.DrawArea);
263					}
264				}
265			});
266		}
267		#endregion
268
269		#region DrawMultiLineTextAligned (Static)
270		/// <summary>
271		/// Draw multi line text aligned
272		/// </summary>
273		[Test]
274		public static void DrawMultiLineTextAligned()
275		{
276			// Get the number of available horizontal
277			int horizontalAlignmentModes =
278				EnumHelper.GetCount<HorizontalAlignment>();
279			// and vertical alignment modes
280			int verticalAlignmentModes =
281				EnumHelper.GetCount<VerticalAlignment>();
282
283			// Create fonts with every horizontal and vertical alignment mode
284			Font[,] fonts =
285				new Font[horizontalAlignmentModes,verticalAlignmentModes];
286			for (int hModeId = 0; hModeId < horizontalAlignmentModes; hModeId++)
287			{
288				for (int vModeId = 0; vModeId < verticalAlignmentModes; vModeId++)
289				{
290					fonts[hModeId, vModeId] = new Font(Font.Default,
291						(HorizontalAlignment)hModeId, (VerticalAlignment)vModeId);
292				}
293			}
294
295			Application.Start(delegate
296			{
297				// Draw outline of the area we use to draw all fonts
298				Rectangle drawArea = ScreenSpace.DrawArea.ScaleCentered(0.99f);
299				Rect.DrawOutline(ScreenSpace.DrawArea, Color.Blue);
300
301				// Show a text with every possible horizontal and vertical alignment
302				for (int hModeId = 0; hModeId < horizontalAlignmentModes; hModeId++)
303				{
304					for (int vModeId = 0; vModeId < verticalAlignmentModes; vModeId++)
305					{
306						// While the code for all fonts is the same, the actual rendering
307						// will appear at different locations on the screen depending on
308						// the current alignment combination.
309						Font font = fonts[hModeId, vModeId];
310						string text =
311							"This text is in the" + Environment.NewLine +
312							font.VerticalAlignment + " " + font.HorizontalAlignment +
313							Environment.NewLine + "alignment mode.";
314						font.Draw(text, drawArea);
315					} // for
316				} // for
317			});
318		}
319		#endregion
320
321		#region DrawTextClipped (Static)
322		/// <summary>
323		/// Draw text clipped
324		/// </summary>
325		[Test]
326		public static void DrawTextClipped()
327		{
328			const string Text = "That text should be only inside red box.";
329			Point textAreaPos = new Point(0.2f, 0.45f);
330
331			Application.Start(delegate
332			{
333				Size maxTextSize = Font.Default.Measure(Text);
334				Font.Default.Draw(
335					Text + "If you are still seeing text outside of the" +
336					" shown box,\nthen you know the clipping doesn't work :(",
337					new Rectangle(textAreaPos, maxTextSize));
338				Rect.DrawOutline(new Rectangle(textAreaPos, maxTextSize), Color.Red);
339			});
340		}
341		#endregion
342
343		#region DrawTextWordWrapped (Static)
344		/// <summary>
345		/// Draw text word wrapped
346		/// </summary>
347		[Test]
348		public static void DrawTextWordWrapped()
349		{
350			string text = "long loong looong loooong text";
351			text += Environment.NewLine + "Newline";
352
353			Font infoFont = new Font(Font.Default, Color.White,
354				HorizontalAlignment.Left, VerticalAlignment.Top, true);
355
356			Rectangle textArea = new Rectangle(0.2f, 0.45f, 0.135f, 0.05f);
357			Application.Start(delegate
358			{
359				infoFont.Draw(text, textArea);
360				Rect.DrawOutline(textArea, Color.Red);
361
362				BaseMouse mouse = Input.Mouse;
363				if (Input.Gestures.IsDrag)
364				{
365					// Compute the drag movement per tick
366					textArea.Size += (Size)(mouse.Movement);
367				} // if
368			});
369		}
370		#endregion
371
372		#region DrawTextResolutionBased (Static)
373		/// <summary>
374		/// Draw text resolution based
375		/// </summary>
376		[Test]
377		public static void DrawTextResolutionBased()
378		{
379			Application.Start(delegate
380			{
381				string fontInfoText =
382					"Current resolution: '" + Settings.Resolution + "'\n" +
383					"Current font size: '" + Font.Default.CurrentFontSize + "'";
384				Font.Default.Draw(fontInfoText, ScreenSpace.DrawArea);
385
386				// Switch the 4 supported font scaling-steps by pressing the numbers
387				// 1-4 on the keyboard
388				if (Input.Keyboard.IsReleased(InputButton.D1))
389				{
390					Application.Window.Resize(480, 320);
391				} // if
392				else if (Input.Keyboard.IsReleased(InputButton.D2))
393				{
394					Application.Window.Resize(800, 480);
395				} // if
396				else if (Input.Keyboard.IsReleased(InputButton.D3))
397				{
398					Application.Window.Resize(1024, 768);
399				} // if
400				else if (Input.Keyboard.IsReleased(InputButton.D4))
401				{
402					Application.Window.Resize(1920, 1080);
403				} // if
404			});
405		}
406		#endregion
407
408		#region RotationResearchTest (Static)
409		/// <summary>
410		/// Rotation research test
411		/// </summary>
412		[Test]
413		private static void RotationResearchTest()
414		{
415			Rectangle textArea = new Rectangle(0.5f, 0.5f, 0.2f,
416				0.025f);
417
418			Rectangle glyphArea = new Rectangle(0.0f, 0.0f, 0.015f,
419				0.02f);
420
421			float rotation = 0.0f;
422			//rotation = 1.0f;
423			Application.Start(delegate
424			{
425				// Rotate 10 degree per second
426				rotation += 22.5f * Time.Delta;
427
428				Rect.DrawOutline(textArea, Color.Red, rotation);
429
430				Point startPos = new Point(textArea.Left, textArea.Center.Y);
431
432				Point rotationOffset =
433					(startPos + new Point(glyphArea.Width / 2.0f, 0.0f)) -
434					textArea.Center;
435
436				rotationOffset.Rotate(rotation);
437
438				Point nextGlyphCenterPoint = textArea.Center + rotationOffset;
439
440				Line.Draw(textArea.Center, nextGlyphCenterPoint, Color.Orange);
441				//Line.Draw(textArea.Center, textArea.BottomRight, Color.Orange);
442
443				Rect.DrawOutline(
444					Rectangle.FromCenter(nextGlyphCenterPoint, glyphArea.Size),
445					Color.Green,
446					rotation);
447			});
448		}
449		#endregion
450
451		#region DrawSingleLineRotatedText (Static)
452		/// <summary>
453		/// Draw single line rotated text
454		/// </summary>
455		[Test]
456		public static void DrawSingleLineRotatedText()
457		{
458			string text = "Jackdaws love my big sphinx of quartz.";
459
460			Rectangle textArea = new Rectangle(0.5f, 0.5f,
461				// We don't care about the size, do not clip!
462				0.0f, 0.0f);//0.2f, infoFont.LineHeight);
463
464			float rotation = 0.0f;
465			Application.Start(delegate
466			{
467				// Draw reference how the unrotated text should look like
468				Font.Default.Draw(text,
469					Rectangle.FromCenter(0.5f, 0.25f, 0.25f, 0.25f));
470
471				// Rotate 90 degree per second (4 seconds for a full rotation)
472				if (Input.Keyboard.IsPressed(InputButton.Shift) == false)
473				{
474					// Only rotate if Shift is not pressed
475					rotation += 90.0f * Time.Delta;
476				}
477
478				// Helper to see the circle we are rotating around in
479				if (Input.Keyboard.IsPressed(InputButton.Space))
480				{
481					Circle.DrawOutline(new Point(0.5f, 0.5f), 0.2f, Color.Red);
482				}
483
484				// Helpers to see if text is still sharp at 0, 90, 180 and 270 degrees
485				if (Input.Keyboard.IsPressed(InputButton.A))
486				{
487					rotation = 0;
488				}
489				else if (Input.Keyboard.IsPressed(InputButton.B))
490				{
491					rotation = 90;
492				}
493				else if (Input.Keyboard.IsPressed(InputButton.C))
494				{
495					rotation = 180;
496				}
497				else if (Input.Keyboard.IsPressed(InputButton.D))
498				{
499					rotation = 270;
500				}
501
502				Font.Default.Draw(text, textArea, rotation, Point.Zero);
503			});
504		}
505		#endregion
506
507		#region CompareFontKerning (LongRunning)
508		/// <summary>
509		/// Compare font kerning
510		/// </summary>
511		[Test, Category("LongRunning")]
512		public static void CompareFontKerning()
513		{
514			// First define the fonts
515			Font noKerningFont = new Font(
516				FontData.Get("VerdanaNoKerning", 28, FontStyle.AddOutline),
517				HorizontalAlignment.Left);
518			Font kerningFont = new Font(
519				FontData.Get("Verdana", 28, FontStyle.AddOutline),
520				HorizontalAlignment.Left);
521
522			// As next the text we want to see with and without kerning
523			const string Text = "P. and V.";
524
525			// also the text area (reference) for the text drawing
526			Rectangle textArea = new Rectangle(0.5f, 0.4f, 0.3f,
527				kerningFont.LineHeight);
528			Application.Start(delegate
529			{
530				// Now just show the text without kerning
531				noKerningFont.Draw("Without kerning: ", textArea.Move(-0.3f, 0.0f));
532				noKerningFont.Draw(Text, textArea);
533
534				// And once with kerning to see the difference
535				noKerningFont.Draw("With kerning: ", textArea.Move(-0.3f,
536					kerningFont.LineHeight));
537				kerningFont.Draw(Text, textArea.Move(0.0f,
538					kerningFont.LineHeight));
539			});
540		}
541		#endregion
542
543		#region DrawMultiLineRotatedText (LongRunning)
544		/// <summary>
545		/// Draw multi line rotated text
546		/// </summary>
547		[Test, Category("LongRunning")]
548		public static void DrawMultiLineRotatedText()
549		{
550			string text =
551				"Jackdaws love my big sphinx of quartz.\n" +
552				"But another idiom is:\r\n" +
553				"Six big juicy steaks sizzled.";
554
555			Rectangle textArea =
556				new Rectangle(0.35f, 0.25f, 0.3f, Font.Default.LineHeight * 3.0f);
557
558			float rotation = 0.0f;
559			Application.Start(delegate
560			{
561				// Draw reference how the unrotated text should look like
562				Font.Default.Draw(text, textArea, 0.0f, Point.Zero);
563
564				// Rotate 90 degree per second
565				rotation += 90.0f * Time.Delta;
566
567				Font.Default.Draw(text, textArea.Move(0.0f, 0.25f), rotation,
568					Point.Zero);
569			});
570		}
571		#endregion
572
573		#region DrawPerformanceTest
574		/// <summary>
575		/// Draw performance test
576		/// </summary>
577		[Test, Category("Visual")]
578		public static void DrawPerformanceTest()
579		{
580			string[] texts = new[]
581			{
582				"Hello World",
583				" !\"#$%&'()*+,-./0123456789:;<=>?@",
584				"ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`",
585				"abcdefghijklmnopqrstuvwxyz{|}~",
586				"That kind of drawing text is interresting.",
587				"Hello World"
588			};
589
590			Font infoFont = new Font(Font.Default,
591				HorizontalAlignment.Left, VerticalAlignment.Top);
592
593			Size textSize = new Size(1.0f, infoFont.LineHeight * 3);
594			Application.Start(delegate
595			{
596
597				for (int index = 0; index < texts.Length; index++)
598				{
599					Rectangle textArea = new Rectangle(
600						new Point(0.1f, 0.2f + index * infoFont.LineHeight * 2.5f),
601						textSize);
602
603					// old: Judge: Win 7, Core i7 920, 6 GB Ram, Ati 5750 HD
604					// - Draw with GlyphInfo[] -> ~2540 FPS
605					// - Draw with Geometry -> ~3170 FPS
606
607					// Optimized to ~10000 FPS on Sandy Bridge 4Ghz, GeForce 480.
608					// without swapbuffer/clear/render this is ~250000 FPS (in debug
609					// mode, in release mode we can reach 3 times that)
610
611					// Drawing by cached glyph info's
612					infoFont.Draw(texts[index], textArea, 0.0f, Point.Zero);
613
614					//				on the mobile devices
615					//// Drawing by cached geomtry
616					//infoFont.Draw(texts[index], textArea, 0.0f, Point.Zero);
617				}
618
619				//no thanks to auto quit
620				//if (Time.Seconds >= 3)
621				//{
622				//  Application.Quit();
623				//} // if
624			});
625		}
626		#endregion
627
628		#region TestCharCollectingPerformance (Static)
629		/// <summary>
630		/// Test char collecting
631		/// </summary>
632		[Test]
633		private static void TestCharCollectingPerformance()
634		{
635			string text = "ehoiwrhaenf ierfh ioei hEWOIHoeirjnlsdnflsdn osdjfsdfö " +
636			              "ashnfdeir aweho nklidfhwioerhoewir knskdfla jrfweimwaemfijefe ids " +
637			              "löginjaqw ioiai wrjnuiu na ua safooiuroiwrpewr jioa djijwrweruqwer" +
638			              "iodjpjanvlxic9prtgopüaj opdu 39483 rawü ß asd 0po asd ak lkjdfau80" +
639			              "ok09i2jqaw 9 9a du opjo34eqwrjfaj oas parörpo3ir0 wakasj ööas foMF" +
640			              "esifjhaierf idsfj lijef iodsfjinnhdf dfhhidsio idinqäppa osao oad";
641
642			int Loops = 100000;
643
644			char[] textChars = text.ToCharArray();
645
646			Stopwatch time = new Stopwatch();
647
648			List<char> charList = new List<char>();
649			time.Start();
650			for (int i = 0; i < Loops; i++)
651			{
652				for (int charId = 0; charId < textChars.Length; charId++)
653				{
654					charList.Add(textChars[charId]);
655				}
656				charList.Clear();
657			}
658			time.Stop();
659			Log.Info("'" + time.ElapsedMilliseconds + "' ms elapsed.");
660
661			string charString = "";
662			time.Restart();
663			for (int i = 0; i < Loops; i++)
664			{
665				for (int charId = 0; charId < textChars.Length; charId++)
666				{
667					charString += textChars[charId];
668				}
669				charString = "";
670			}
671			time.Stop();
672			Log.Info("'" + time.ElapsedMilliseconds + "' ms elapsed.");
673
674			StringBuilder charBuilder = new StringBuilder();
675			time.Restart();
676			for (int i = 0; i < Loops; i++)
677			{
678				for (int charId = 0; charId < textChars.Length; charId++)
679				{
680					charBuilder.Append(textChars[charId]);
681				}
682				charBuilder.Clear();
683			}
684			time.Stop();
685			Log.Info("'" + time.ElapsedMilliseconds + "' ms elapsed.");
686
687			List<char> list = new List<char>();
688			time.Restart();
689			for (int i = 0; i < Loops; i++)
690			{
691				char[] chars = text.ToCharArray();
692				for (int charId = 0; charId < chars.Length; charId++)
693				{
694					list.Add(chars[charId]);
695				}
696				charString = "";
697			}
698			time.Stop();
699			Log.Info("'" + time.ElapsedMilliseconds + "' ms elapsed.");
700
701			list = new List<char>();
702			time.Restart();
703			for (int i = 0; i < Loops; i++)
704			{
705				for (int charId = 0; charId < text.Length; charId++)
706				{
707					list.Add(text[charId]);
708				}
709				charString = "";
710			}
711			time.Stop();
712			Log.Info("'" + time.ElapsedMilliseconds + "' ms elapsed.");
713		}
714		#endregion
715
716		#region TestFontRamBug (Static)
717		/// <summary>
718		/// Test the bug #4015 with massively increasing ram as posted here:
719		/// http://forum.deltaengine.net/yaf_postsm851_-Bug--Or-WTF-RAM-Faill.aspx#post851
720		/// </summary>
721		[Test]
722		public static void TestFontRamBug()
723		{
724			int tmp = 0;
725			string inputText;
726			Application.Start(delegate
727			{
728				// Constantly change the text to be rendered.
729				tmp++;
730				inputText = "Level1 \n" + tmp;
731				Font.Default.Draw(inputText, new Rectangle(0.025f, 0.45f, 0.3f, 0.3f));
732			});
733		}
734		#endregion
735	}
736}
737