mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-03-26 21:15:18 +00:00
Added missing files from working copy.
This commit is contained in:
parent
5e449dabd4
commit
18cb4d2432
201
Source/Utilities/Graphics/AlphaTexture2D.cs
Normal file
201
Source/Utilities/Graphics/AlphaTexture2D.cs
Normal file
|
@ -0,0 +1,201 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Imaging;
|
||||
|
||||
namespace OpenTK.Graphics
|
||||
{
|
||||
/// <summary>
|
||||
/// Encapsulates an OpenGL texture.
|
||||
/// </summary>
|
||||
class AlphaTexture2D : IGraphicsResource
|
||||
{
|
||||
#region Fields
|
||||
|
||||
GraphicsContext context;
|
||||
int id;
|
||||
int width, height;
|
||||
bool disposed;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new Texture.
|
||||
/// </summary>
|
||||
public AlphaTexture2D(int width, int height)
|
||||
{
|
||||
Width = width;
|
||||
Height = height;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IGraphicsResource Members
|
||||
|
||||
GraphicsContext IGraphicsResource.Context { get { return context; } }
|
||||
|
||||
int IGraphicsResource.Id
|
||||
{
|
||||
get
|
||||
{
|
||||
if (id == 0)
|
||||
{
|
||||
GraphicsContext.Assert();
|
||||
context = GraphicsContext.CurrentContext;
|
||||
|
||||
id = GL.GenTexture();
|
||||
if (id == 0)
|
||||
throw new GraphicsResourceException(String.Format("Texture creation failed, (Error: {0})", GL.GetError()));
|
||||
|
||||
// Ensure the texture is allocated.
|
||||
GL.BindTexture(TextureTarget.Texture2D, id);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)All.Linear);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)All.Linear);
|
||||
if (GL.SupportsExtension("Version12"))
|
||||
{
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.ClampToEdge);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.ClampToEdge);
|
||||
}
|
||||
else
|
||||
{
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)All.Clamp);
|
||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)All.Clamp);
|
||||
}
|
||||
|
||||
GL.TexImage2D(TextureTarget.Texture2D, 0, PixelInternalFormat.Alpha, Width, Height, 0,
|
||||
OpenTK.Graphics.PixelFormat.Rgba, PixelType.UnsignedByte, IntPtr.Zero);
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Public Members
|
||||
|
||||
#region public int Width
|
||||
|
||||
/// <summary>Gets the width of the texture.</summary>
|
||||
public int Width { get { return width; } private set { width = value; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region public int Height
|
||||
|
||||
/// <summary>Gets the height of the texture.</summary>
|
||||
public int Height { get { return height; } private set { height = value; } }
|
||||
|
||||
#endregion
|
||||
|
||||
#region WriteRegion
|
||||
|
||||
public void WriteRegion(Rectangle source, Rectangle target, int mipLevel, Bitmap bitmap)
|
||||
{
|
||||
if (bitmap == null)
|
||||
throw new ArgumentNullException("data");
|
||||
|
||||
GraphicsUnit unit = GraphicsUnit.Pixel;
|
||||
|
||||
if (!bitmap.GetBounds(ref unit).Contains(source))
|
||||
throw new InvalidOperationException("The source Rectangle is larger than the Bitmap.");
|
||||
|
||||
if (mipLevel < 0)
|
||||
throw new ArgumentOutOfRangeException("mipLevel");
|
||||
|
||||
Bind();
|
||||
|
||||
BitmapData data = bitmap.LockBits(source, ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
|
||||
GL.PushClientAttrib(ClientAttribMask.ClientPixelStoreBit);
|
||||
try
|
||||
{
|
||||
GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1);
|
||||
GL.PixelStore(PixelStoreParameter.UnpackRowLength, bitmap.Width);
|
||||
GL.TexSubImage2D(TextureTarget.Texture2D, mipLevel,
|
||||
target.Left, target.Top,
|
||||
target.Width, target.Height,
|
||||
OpenTK.Graphics.PixelFormat.Rgba,
|
||||
PixelType.UnsignedByte, data.Scan0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
GL.PopClientAttrib();
|
||||
}
|
||||
|
||||
bitmap.UnlockBits(data);
|
||||
}
|
||||
|
||||
public void WriteRegion(TextureRegion2D region, int mipLevel)
|
||||
{
|
||||
if (mipLevel < 0)
|
||||
throw new ArgumentOutOfRangeException("miplevel");
|
||||
|
||||
GL.TexSubImage2D(TextureTarget.Texture2D, mipLevel,
|
||||
region.Rectangle.X, region.Rectangle.Y,
|
||||
region.Rectangle.Width, region.Rectangle.Height,
|
||||
PixelFormat.Bgra, PixelType.UnsignedByte, region);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region ReadRegion
|
||||
|
||||
public TextureRegion2D ReadRegion(Rectangle rect, int mipLevel)
|
||||
{
|
||||
if (mipLevel < 0)
|
||||
throw new ArgumentOutOfRangeException("miplevel");
|
||||
|
||||
TextureRegion2D<int> region = new TextureRegion2D<int>(rect);
|
||||
|
||||
GL.GetTexImage(TextureTarget.Texture2D, mipLevel, PixelFormat.Bgra, PixelType.UnsignedByte, region.Data);
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Bind
|
||||
|
||||
public void Bind()
|
||||
{
|
||||
GL.BindTexture(TextureTarget.Texture2D, (this as IGraphicsResource).Id);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region IDisposable Members
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
void Dispose(bool manual)
|
||||
{
|
||||
if (!disposed)
|
||||
{
|
||||
if (manual)
|
||||
{
|
||||
GL.DeleteTexture(id);
|
||||
}
|
||||
disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
~AlphaTexture2D()
|
||||
{
|
||||
GraphicsContext context = (this as IGraphicsResource).Context;
|
||||
if (context != null)
|
||||
(context as IGraphicsContextInternal).RegisterForDisposal(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
268
Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer .cs
Normal file
268
Source/Utilities/Graphics/Text/GdiPlusGlyphRasterizer .cs
Normal file
|
@ -0,0 +1,268 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
|
||||
using OpenTK.Graphics.Text;
|
||||
using OpenTK.Platform;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace OpenTK.Graphics.Text
|
||||
{
|
||||
class GdiPlusGlyphRasterizer : IGlyphRasterizer
|
||||
{
|
||||
#region Fields
|
||||
|
||||
Dictionary<TextBlock, TextExtents> block_cache = new Dictionary<TextBlock, TextExtents>();
|
||||
System.Drawing.Graphics graphics = System.Drawing.Graphics.FromImage(new Bitmap(1, 1));
|
||||
|
||||
IntPtr[] regions = new IntPtr[GdiPlus.MaxMeasurableCharacterRanges];
|
||||
CharacterRange[] characterRanges = new CharacterRange[GdiPlus.MaxMeasurableCharacterRanges];
|
||||
|
||||
TextExtents extents = new TextExtents();
|
||||
|
||||
// Check the constructor, too, for additional flags.
|
||||
static readonly StringFormat default_string_format = StringFormat.GenericTypographic;
|
||||
static readonly StringFormat load_glyph_string_format = StringFormat.GenericDefault;
|
||||
|
||||
static readonly char[] newline_characters = new char[] { '\n', '\r' };
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructors
|
||||
|
||||
static GdiPlusGlyphRasterizer()
|
||||
{
|
||||
default_string_format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
|
||||
}
|
||||
|
||||
public GdiPlusGlyphRasterizer()
|
||||
{ }
|
||||
|
||||
#endregion
|
||||
|
||||
#region IGlyphRasterizer Members
|
||||
|
||||
#region Rasterize
|
||||
|
||||
public Bitmap Rasterize(Glyph glyph)
|
||||
{
|
||||
using (Bitmap bmp = new Bitmap((int)(2 * glyph.Font.Size), (int)(2 * glyph.Font.Size)))
|
||||
using (System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(bmp))
|
||||
{
|
||||
// Small sizes look blurry without gridfitting, so turn that on.
|
||||
if (glyph.Font.Size <= 18.0f)
|
||||
gfx.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
|
||||
else
|
||||
gfx.TextRenderingHint = TextRenderingHint.AntiAlias;
|
||||
|
||||
gfx.Clear(Color.Transparent);
|
||||
gfx.DrawString(glyph.Character.ToString(), glyph.Font, Brushes.White, PointF.Empty);
|
||||
|
||||
Rectangle tight_rect = FindEdges(bmp);
|
||||
Bitmap tight_glyph = bmp.Clone(tight_rect, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
//new Bitmap(tight_rect.Width, tight_rect.Height);
|
||||
//return bmp.Clone(FindEdges(bmp), System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||
return tight_glyph;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MeasureText
|
||||
|
||||
//public RectangleF MeasureText(TextBlock block)
|
||||
//{
|
||||
// return MeasureText(block, ref extents);
|
||||
//}
|
||||
|
||||
public TextExtents MeasureText(TextBlock block)
|
||||
{
|
||||
// First, check if we have cached this text block. Do not use block_cache.TryGetValue, to avoid thrashing
|
||||
// the user's TextBlockExtents struct.
|
||||
if (block_cache.ContainsKey(block))
|
||||
return block_cache[block];
|
||||
|
||||
// If this block is not cached, we have to measure it and place it in the cache.
|
||||
MeasureTextExtents(block, ref extents);
|
||||
if ((block.Options & TextPrinterOptions.NoCache) == 0)
|
||||
block_cache.Add(block, new TextExtents(extents.BoundingBox, extents.GlyphExtents));
|
||||
|
||||
return extents;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MeasureGlyph
|
||||
|
||||
public RectangleF MeasureGlyph(Glyph glyph)
|
||||
{
|
||||
using (Bitmap bmp = Rasterize(glyph))
|
||||
{
|
||||
return FindEdges(bmp);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private Members
|
||||
|
||||
#region MeasureTextExtents
|
||||
|
||||
void MeasureTextExtents(TextBlock block, ref TextExtents extents)
|
||||
{
|
||||
// Todo: Parse layout options:
|
||||
StringFormat format = default_string_format;
|
||||
|
||||
extents.Clear();
|
||||
|
||||
PointF origin = PointF.Empty;
|
||||
SizeF size = SizeF.Empty;
|
||||
|
||||
IntPtr native_graphics = GdiPlus.GetNativeGraphics(graphics);
|
||||
IntPtr native_font = GdiPlus.GetNativeFont(block.Font);
|
||||
IntPtr native_string_format = GdiPlus.GetNativeStringFormat(format);
|
||||
|
||||
int height = 0;
|
||||
|
||||
// It seems that the mere presence of \n and \r characters
|
||||
// is enough for Mono to botch the layout (even if these
|
||||
// characters are not processed.) We'll need to find a
|
||||
// different way to perform layout on Mono, probably
|
||||
// through Pango.
|
||||
// Todo: This workaround allocates memory.
|
||||
//if (Configuration.RunningOnMono)
|
||||
{
|
||||
string[] lines = block.Text.Replace("\r", String.Empty).Split('\n');
|
||||
foreach (string s in lines)
|
||||
{
|
||||
extents.AddRange(MeasureGlyphExtents(
|
||||
s, height, 0, s.Length, block.LayoutRectangle,
|
||||
native_graphics, native_font, native_string_format));
|
||||
height += block.Font.Height;
|
||||
}
|
||||
}
|
||||
|
||||
extents.BoundingBox = new RectangleF(extents[0].X, extents[0].Y, extents[extents.Count - 1].Right, extents[extents.Count - 1].Bottom);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region MeasureGlyphExtents
|
||||
|
||||
// Gets the bounds of each character in a line of text.
|
||||
// The line is processed in blocks of 32 characters (GdiPlus.MaxMeasurableCharacterRanges).
|
||||
IEnumerable<RectangleF> MeasureGlyphExtents(string text, int height, int line_start, int line_length,
|
||||
RectangleF layoutRect, IntPtr native_graphics, IntPtr native_font, IntPtr native_string_format)
|
||||
{
|
||||
RectangleF rect = new RectangleF();
|
||||
int line_end = line_start + line_length;
|
||||
while (line_start < line_end)
|
||||
{
|
||||
//if (text[line_start] == '\n' || text[line_start] == '\r')
|
||||
//{
|
||||
// line_start++;
|
||||
// continue;
|
||||
//}
|
||||
|
||||
int num_characters = (line_end - line_start) > GdiPlus.MaxMeasurableCharacterRanges ?
|
||||
GdiPlus.MaxMeasurableCharacterRanges :
|
||||
line_end - line_start;
|
||||
int status = 0;
|
||||
|
||||
for (int i = 0; i < num_characters; i++)
|
||||
{
|
||||
characterRanges[i] = new CharacterRange(line_start + i, 1);
|
||||
|
||||
IntPtr region;
|
||||
status = GdiPlus.CreateRegion(out region);
|
||||
regions[i] = region;
|
||||
Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status));
|
||||
}
|
||||
|
||||
status = GdiPlus.SetStringFormatMeasurableCharacterRanges(native_string_format, num_characters, characterRanges);
|
||||
Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status));
|
||||
|
||||
status = GdiPlus.MeasureCharacterRanges(native_graphics, text, text.Length,
|
||||
native_font, ref layoutRect, native_string_format, num_characters, regions);
|
||||
Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status));
|
||||
|
||||
for (int i = 0; i < num_characters; i++)
|
||||
{
|
||||
GdiPlus.GetRegionBounds(regions[i], native_graphics, ref rect);
|
||||
Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status));
|
||||
GdiPlus.DeleteRegion(regions[i]);
|
||||
Debug.Assert(status == 0, String.Format("GDI+ error: {0}", status));
|
||||
|
||||
rect.Y += height;
|
||||
|
||||
yield return rect;
|
||||
}
|
||||
|
||||
line_start += num_characters;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region FindEdges
|
||||
|
||||
Rectangle FindEdges(Bitmap bmp)
|
||||
{
|
||||
return Rectangle.FromLTRB(
|
||||
FindLeftEdge(bmp),
|
||||
FindTopEdge(bmp),
|
||||
FindRightEdge(bmp),
|
||||
FindBottomEdge(bmp));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Find[Left|Right|Top|Bottom]Edge
|
||||
|
||||
// Iterates through the bmp, and returns the first row or line that contains a non-transparent pixels.
|
||||
|
||||
int FindLeftEdge(Bitmap bmp)
|
||||
{
|
||||
for (int x = 0; x < bmp.Width; x++)
|
||||
for (int y = 0; y < bmp.Height; y++)
|
||||
if (bmp.GetPixel(x, y).A != 0)
|
||||
return x;
|
||||
|
||||
return bmp.Width;
|
||||
}
|
||||
|
||||
int FindRightEdge(Bitmap bmp)
|
||||
{
|
||||
for (int x = bmp.Width - 1; x >= 0; x--)
|
||||
for (int y = 0; y < bmp.Height; y++)
|
||||
if (bmp.GetPixel(x, y).A != 0)
|
||||
return x + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FindTopEdge(Bitmap bmp)
|
||||
{
|
||||
// Don't trim the top edge, because the layout engine expects it to be 0.
|
||||
return 0;
|
||||
}
|
||||
|
||||
int FindBottomEdge(Bitmap bmp)
|
||||
{
|
||||
for (int y = bmp.Height - 1; y >= 0; y--)
|
||||
for (int x = 0; x < bmp.Width; x++)
|
||||
if (bmp.GetPixel(x, y).A != 0)
|
||||
return y + 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue