/// <summary>
    /// Renders a <see cref="ThemeImage"/>.
    /// </summary>
    /// <param name="bounds">The control's bounding rectangle.</param>
    /// <param name="image">The image.</param>
    /// <param name="opacity">The opacity.</param>
    /// <param name="transform">The render transform.</param>
    /// <remarks>
    /// This method uses the <paramref name="image"/> properties (alignment, margin, etc.) and the 
    /// render transformation to render the image into the target (<paramref name="bounds"/>).
    /// </remarks>
    public void RenderImage(RectangleF bounds, ThemeImage image, float opacity, RenderTransform transform)
    {
      if (image == null)
        return;

      // Get the texture atlas containing the image.
      Texture2D texture = (image.Texture != null) ? image.Texture.Texture : _defaultTexture;
      
      // Get bounds without margin.
      Rectangle source = image.SourceRectangle;
      Vector4 margin = image.Margin;
      bounds.X += margin.X;
      bounds.Y += margin.Y;
      bounds.Width -= margin.X + margin.Z;
      bounds.Height -= margin.Y + margin.W;

      // Get tint color and premultiply alpha.
      Vector4 colorVector = image.Color.ToVector4();
      colorVector.W *= opacity;

      Color color = Color.FromNonPremultiplied(colorVector);
#else
      Color color = ColorFromNonPremultiplied(colorVector);



      if (image.HorizontalAlignment == HorizontalAlignment.Stretch || image.VerticalAlignment == VerticalAlignment.Stretch)
      {
        // Draw stretched image using a 9-grid layout.
        RenderStretchedImage(texture, image, bounds, transform, color);
      }
      else
      {
        // Draw a non-stretched image.
        RenderImage(texture, bounds, source, image.HorizontalAlignment, image.VerticalAlignment, image.TileMode, transform, color);
      }
    }
    /// <summary>
    /// Renders an image with alignment and optional tiling.
    /// </summary>
    /// <param name="texture">The UI texture.</param>
    /// <param name="area">The area to fill.</param>
    /// <param name="source">The source rectangle of the image in the UI texture.</param>
    /// <param name="horizontalAlignment">The horizontal alignment.</param>
    /// <param name="verticalAlignment">The vertical alignment.</param>
    /// <param name="tileMode">The tile mode.</param>
    /// <param name="transform">The render transform.</param>
    /// <param name="color">The tint color.</param>
    private void RenderImage(Texture2D texture, RectangleF area, Rectangle source, HorizontalAlignment horizontalAlignment, VerticalAlignment verticalAlignment, TileMode tileMode, RenderTransform transform, Color color)
    {
      bool tileHorizontally = (tileMode == TileMode.TileX || tileMode == TileMode.TileXY);
      bool tileVertically = (tileMode == TileMode.TileY || tileMode == TileMode.TileXY);

      // Compute destination rectangle of base image (left/top tile).
      RectangleF destination;
      switch (horizontalAlignment)
      {
        case HorizontalAlignment.Center:
          destination.X = (float)Math.Floor(area.X + area.Width / 2.0f - source.Width / 2.0f);    // Always round down for consistent results!
          destination.Width = source.Width;

          if (tileHorizontally)
            while (destination.X > area.X)
              destination.X -= destination.Width;

          break;
        
        case HorizontalAlignment.Right:
          destination.X = area.X + area.Width - source.Width;
          destination.Width = source.Width;

          if (tileHorizontally)
            while (destination.X > area.X)
              destination.X -= destination.Width;

          break;
        
        case HorizontalAlignment.Stretch:
          destination.X = area.X;
          destination.Width = area.X + area.Width - source.Width;
          break;
        
        default:
          destination.X = area.X;
          destination.Width = source.Width;
          break;
      }

      switch (verticalAlignment)
      {
        case VerticalAlignment.Center:
          destination.Y = (float)Math.Floor(area.Y + area.Height / 2.0f - source.Height / 2.0f);  // Always round down for consistent results!
          destination.Height = source.Height;

          if (tileVertically)
            while (destination.Y > area.Y)
              destination.Y -= destination.Height;

          break;

        case VerticalAlignment.Bottom:
          destination.Y = area.Y + area.Height - source.Height;
          destination.Height = source.Height;
          
          if (tileVertically)
            while (destination.Y > area.Y)
              destination.Y -= destination.Height;

          break;

        case VerticalAlignment.Stretch:
          destination.Y = area.Y;
          destination.Height = area.Height;
          break;

        default:
          destination.Y = area.Y;
          destination.Height = source.Height;
          break;
      }

      switch (tileMode)
      {
        case TileMode.None:
          ClipX(area, ref destination, ref source);
          ClipY(area, ref destination, ref source);
          transform.Draw(SpriteBatch, texture, destination, source, color);
          break;

        case TileMode.TileX:
          ClipY(area, ref destination, ref source);
          RenderTileX(texture, area, destination, source, transform, color);
          break;
        
        case TileMode.TileY:
          ClipX(area, ref destination, ref source);
          RenderTileY(texture, area, destination, source, transform, color);
          break;
        
        case TileMode.TileXY:
          RenderTileXY(texture, area, destination, source, transform, color);
          break;
      }      
    }
    /// <summary>
    /// Renders an image with alignment and optional stretching.
    /// </summary>
    /// <param name="texture">The UI texture.</param>
    /// <param name="image">The image.</param>
    /// <param name="area">The area to fill.</param>
    /// <param name="transform">The render transform.</param>
    /// <param name="color">The tint color.</param>
    private void RenderStretchedImage(Texture2D texture, ThemeImage image, RectangleF area, RenderTransform transform, Color color)
    {
      Rectangle source = image.SourceRectangle;
      int left = (int)image.Border.X;
      int top = (int)image.Border.Y;
      int right = (int)image.Border.Z;
      int bottom = (int)image.Border.W;

      switch (image.HorizontalAlignment)
      {
        case HorizontalAlignment.Center:
          area.X = (float)Math.Floor(area.X + area.Width / 2.0f - source.Width / 2.0f); // Always round down for consistent results!
          left = source.Width;
          right = 0;
          break;
        case HorizontalAlignment.Left:
          left = source.Width;
          right = 0;
          break;
        case HorizontalAlignment.Right:
          left = 0;
          right = source.Width;
          break;
      }

      switch (image.VerticalAlignment)
      {
        case VerticalAlignment.Center:
          area.Y = (float)Math.Floor(area.Y + area.Height / 2.0f - source.Height / 2.0f); // Always round down for consistent results!
          top = source.Height;
          bottom = 0;
          break;
        case VerticalAlignment.Top:
          top = source.Height;
          bottom = 0;
          break;
        case VerticalAlignment.Bottom:
          top = 0;
          bottom = source.Height;
          break;
      }

      // Draw 9-grid layout:
      //
      //   -----------------------
      //   | 1 |      2      | 3 |
      //   -----------------------
      //   |   |             |   |
      //   | 4 |      5      | 6 |
      //   |   |             |   |
      //   -----------------------
      //   | 7 |      8      | 9 |
      //   -----------------------

      Vector2F destinationPosition;
      RectangleF destinationRectangle;
      Rectangle sourceRectangle;

      // Cell #1 (no stretching)
      destinationPosition = new Vector2F(area.X, area.Y);
      sourceRectangle = new Rectangle(source.X, source.Y, left, top);
      transform.Draw(SpriteBatch, texture, destinationPosition, sourceRectangle, color);

      // Cell #2 (horizontal stretching)
      destinationRectangle = new RectangleF(area.X + left, area.Y, area.Width - left - right, top);
      sourceRectangle = new Rectangle(source.X + left, source.Y, source.Width - left - right, top);
      transform.Draw(SpriteBatch, texture, destinationRectangle, sourceRectangle, color);

      // Cell #3 (no stretching)
      destinationPosition = new Vector2F(area.X + area.Width - right, area.Y);
      sourceRectangle = new Rectangle(source.X + source.Width - right, source.Y, right, top);
      transform.Draw(SpriteBatch, texture, destinationPosition, sourceRectangle, color);

      // Cell #4 (vertical stretching)
      destinationRectangle = new RectangleF(area.X, area.Y + top, left, area.Height - top - bottom);
      sourceRectangle = new Rectangle(source.X, source.Y + top, left, source.Height - top - bottom);
      transform.Draw(SpriteBatch, texture, destinationRectangle, sourceRectangle, color);

      // Cell #5 (horizontal and vertical stretching)
      destinationRectangle = new RectangleF(area.X + left, area.Y + top, area.Width - left - right, area.Height - top - bottom);
      sourceRectangle = new Rectangle(source.X + left, source.Y + top, source.Width - left - right, source.Height - top - bottom);
      transform.Draw(SpriteBatch, texture, destinationRectangle, sourceRectangle, color);

      // Cell #6 (vertical stretching)
      destinationRectangle = new RectangleF(area.X + area.Width - right, area.Y + top, right, area.Height - top - bottom);
      sourceRectangle = new Rectangle(source.X + source.Width - right, source.Y + top, right, source.Height - top - bottom);
      transform.Draw(SpriteBatch, texture, destinationRectangle, sourceRectangle, color);

      // Cell #7 (no stretching)
      destinationPosition = new Vector2F(area.X, area.Y + area.Height - bottom);
      sourceRectangle = new Rectangle(source.X, source.Y + source.Height - bottom, left, bottom);
      transform.Draw(SpriteBatch, texture, destinationPosition, sourceRectangle, color);

      // Cell #8 (horizontal stretching)
      destinationRectangle = new RectangleF(area.X + left, area.Y + area.Height - bottom, area.Width - left - right, bottom);
      sourceRectangle = new Rectangle(source.X + left, source.Y + source.Height - bottom, source.Width - left - right, bottom);
      transform.Draw(SpriteBatch, texture, destinationRectangle, sourceRectangle, color);

      // Cell #9 (no stretching)
      destinationPosition = new Vector2F(area.X + area.Width - right, area.Y + area.Height - bottom);
      sourceRectangle = new Rectangle(source.X + source.Width - right, source.Y + source.Height - bottom, right, bottom);
      transform.Draw(SpriteBatch, texture, destinationPosition, sourceRectangle, color);
    }
    /// <summary>
    /// Renders an image repeated times in horizontal and vertical direction.
    /// </summary>
    /// <param name="texture">The UI texture.</param>
    /// <param name="area">The area to fill.</param>
    /// <param name="destination">The destination rectangle of the left, top tile.</param>
    /// <param name="source">The source rectangle of the image in the UI texture.</param>
    /// <param name="transform">The render transform.</param>
    /// <param name="color">The tint color.</param>
    private void RenderTileXY(Texture2D texture, RectangleF area, RectangleF destination, Rectangle source, RenderTransform transform, Color color)
    {
      // Clip and draw first row.
      RectangleF clippedDestination = destination;
      Rectangle clippedSource = source;
      bool bottomEdgeClipped = ClipY(area, ref clippedDestination, ref clippedSource);
      RenderTileX(texture, area, clippedDestination, clippedSource, transform, color);

      if (bottomEdgeClipped)
        return;

      // Draw intermediate rows.
      destination.Y += destination.Height;
      float areaBottom = area.Bottom;
      while (destination.Bottom < areaBottom)
      {
        RenderTileX(texture, area, destination, source, transform, color);
        destination.Y += destination.Height;
      }

      // Clip and draw last row.
      clippedDestination = destination;
      clippedSource = source;
      ClipY(area, ref clippedDestination, ref clippedSource);
      RenderTileX(texture, area, clippedDestination, clippedSource, transform, color);
    }
    /// <summary>
    /// Renders an image repeated times in horizontal direction.
    /// </summary>
    /// <param name="texture">The UI texture.</param>
    /// <param name="area">The area to fill.</param>
    /// <param name="destination">The destination rectangle of the left, top tile.</param>
    /// <param name="source">The source rectangle of the image in the UI texture.</param>
    /// <param name="transform">The render transform.</param>
    /// <param name="color">The tint color.</param>
    private void RenderTileX(Texture2D texture, RectangleF area, RectangleF destination, Rectangle source, RenderTransform transform, Color color)
    {
      // Clip and draw first tile.
      RectangleF clippedDestination = destination;
      Rectangle clippedSource = source;
      bool rightEdgeClipped = ClipX(area, ref clippedDestination, ref clippedSource);
      transform.Draw(SpriteBatch, texture, clippedDestination, clippedSource, color);

      if (rightEdgeClipped)
      {
        // No more tiles to draw.
        return;
      }

      // Draw intermediate tiles.
      destination.X += destination.Width;
      float areaRight = area.Right;
      while (destination.Right < areaRight)
      {
        transform.Draw(SpriteBatch, texture, destination, source, color);
        destination.X += destination.Width;
      }

      // Clip and draw last tile.
      clippedDestination = destination;
      clippedSource = source;
      ClipX(area, ref clippedDestination, ref clippedSource);
      transform.Draw(SpriteBatch, texture, clippedDestination, clippedSource, color);
    }