context: using System;
  using System.Runtime.InteropServices;
  using System.Security;
  using System.Text;
  using ShellUtil;
  
  namespace SFML
  {
      namespace Graphics
      {
          ////////////////////////////////////////////////////////////
          /// <summary>
          /// This class defines a graphical 2D text, that can be drawn on screen
          /// </summary>
          ////////////////////////////////////////////////////////////
          public class Text : Transformable, Drawable
          {
              ////////////////////////////////////////////////////////////
              /// <summary>
              /// Enumerate the string drawing styles
              /// </summary>
              ////////////////////////////////////////////////////////////
              [Flags]
              public enum Styles
              {
                  /// <summary>Regular characters, no style</summary>
                  Regular = 0,
  
                  /// <summary> Characters are bold</summary>
                  Bold = 1 << 0,
  
                  /// <summary>Characters are in italic</summary>
                  Italic = 1 << 1,
  
                  /// <summary>Characters are underlined</summary>
                  Underlined = 1 << 2
              }
  
              private SfmlFont myFont = null;
  
              #region Imports
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern IntPtr sfText_create();
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern IntPtr sfText_copy(IntPtr Text);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern void sfText_destroy(IntPtr CPointer);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern void sfText_setColor(IntPtr CPointer, Color Color);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern Color sfText_getColor(IntPtr CPointer);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern void sfRenderWindow_drawText(
                  IntPtr CPointer, IntPtr Text, ref RenderStates.MarshalData states);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern void sfRenderTexture_drawText(
                  IntPtr CPointer, IntPtr Text, ref RenderStates.MarshalData states);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern void sfText_setUnicodeString(IntPtr CPointer, IntPtr Text);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern void sfText_setFont(IntPtr CPointer, IntPtr Font);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern void sfText_setCharacterSize(IntPtr CPointer, uint Size);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern void sfText_setStyle(IntPtr CPointer, Styles Style);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern IntPtr sfText_getString(IntPtr CPointer);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern IntPtr sfText_getUnicodeString(IntPtr CPointer);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern uint sfText_getCharacterSize(IntPtr CPointer);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern Styles sfText_getStyle(IntPtr CPointer);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern FloatRect sfText_getRect(IntPtr CPointer);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern Vector2 sfText_findCharacterPos(IntPtr CPointer, uint Index);
  
              [DllImport("csfml-graphics-2", CallingConvention = CallingConvention.Cdecl)]
              [SuppressUnmanagedCodeSecurity]
              private static extern FloatRect sfText_getLocalBounds(IntPtr CPointer);
  
              #endregion
  
              ////////////////////////////////////////////////////////////
              /// <summary>
              /// Default constructor
              /// </summary>
              ////////////////////////////////////////////////////////////
              public Text()
                  : this("", null) {}
  
              ////////////////////////////////////////////////////////////
              /// <summary>
              /// Construct the text from a string and a font
              /// </summary>
              /// <param name="str">String to display</param>
              /// <param name="font">Font to use</param>
              ////////////////////////////////////////////////////////////
              public Text(string str, SfmlFont font)
                  : this(str, font, 30) {}
  
              ////////////////////////////////////////////////////////////
              /// <summary>
              /// Construct the text from a string, font and size
              /// </summary>
              /// <param name="str">String to display</param>
              /// <param name="font">Font to use</param>
              /// <param name="characterSize">Base characters size</param>
              ////////////////////////////////////////////////////////////
              public Text(string str, SfmlFont font, uint characterSize)
                  : base(sfText_create())
              {
                  DisplayedString = str;
                  Font = font;
                  CharacterSize = characterSize;
              }
  
              ////////////////////////////////////////////////////////////
              /// <summary>
              /// Construct the text from another text
              /// </summary>
              /// <param name="copy">Text to copy</param>
              ////////////////////////////////////////////////////////////
              public Text(Text copy)
                  : base(sfText_copy(copy.CPointer))
              {
                  Origin = copy.Origin;
                  Position = copy.Position;
                  Rotation = copy.Rotation;
                  Scale = copy.Scale;
  
                  Font = copy.Font;
              }
  
              ////////////////////////////////////////////////////////////
              /// <summary>
              /// Global color of the object
              /// </summary>
              ////////////////////////////////////////////////////////////
              public Color Color
              {
                  get { return sfText_getColor(CPointer); }
                  set { sfText_setColor(CPointer, value); }
              }
  
              ////////////////////////////////////////////////////////////
              /// <summary>
              /// String which is displayed
              /// </summary>
              ////////////////////////////////////////////////////////////
              public string DisplayedString
              {
                  get
                  {
                      // Get a pointer to the source string (UTF-32)
                      IntPtr source = sfText_getUnicodeString(CPointer);
  
                      // Find its length (find the terminating 0)
                      uint length = 0;
                      unsafe
                      {
                          for (uint* ptr = (uint*)source.ToPointer(); *ptr != 0; ++ptr)
                          {
                              length++;
                          }
                      }
  
                      // Copy it to a byte array
                      byte[] sourceBytes = new byte[length * 4];
                      Marshal.Copy(source, sourceBytes, 0, sourceBytes.Length);
  
                      // Convert it to a C# string
                      return Encoding.UTF32.GetString(sourceBytes);
                  }
  
                  set
                  {
                      // Copy the string to a null-terminated UTF-32 byte array
                      byte[] utf32 = Encoding.UTF32.GetBytes(value + '\0');
  
                      // Pass it to the C API
                      unsafe
                      {
                          fixed (byte* ptr = utf32)
                          {
                              sfText_setUnicodeString(CPointer, (IntPtr)ptr);
                          }
                      }
                  }
              }
  
              ////////////////////////////////////////////////////////////
              /// <summary>
              /// Font used to display the text
              /// </summary>
              ////////////////////////////////////////////////////////////
              public SfmlFont Font
              {
                  get { return this.myFont; }
                  set
                  {
                      this.myFont = value;
                      sfText_setFont(CPointer, value != null ? value.CPointer : IntPtr.Zero);
                  }
              }
  
              ////////////////////////////////////////////////////////////
              /// <summary>
              /// Base size of characters
              /// </summary>
              ////////////////////////////////////////////////////////////
              public uint CharacterSize
              {
                  get { return sfText_getCharacterSize(CPointer); }
                  set { sfText_setCharacterSize(CPointer, value); }
              }
  
              ////////////////////////////////////////////////////////////
              /// <summary>
              /// Style of the text (see Styles enum)
              /// </summary>
              ////////////////////////////////////////////////////////////
              public Styles Style
              {
                  get { return sfText_getStyle(CPointer); }
  
gt:                 set { sfText_setStyle(CPointer, value); }