Add workaround for mono GDI+ MeasureCharacterRanges and empty layout rectangles.

This commit is contained in:
the_fiddler 2008-11-28 12:46:58 +00:00
parent 52577946e3
commit 3dd42ada72

View file

@ -27,14 +27,11 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Text;
using System.Drawing;
using System.Drawing.Text;
using OpenTK.Graphics.Text;
using OpenTK.Platform;
using System.Diagnostics; using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging; using System.Drawing.Imaging;
using System.Drawing.Text;
using OpenTK.Platform;
namespace OpenTK.Graphics.Text namespace OpenTK.Graphics.Text
{ {
@ -59,6 +56,8 @@ namespace OpenTK.Graphics.Text
static readonly char[] newline_characters = new char[] { '\n', '\r' }; static readonly char[] newline_characters = new char[] { '\n', '\r' };
static readonly SizeF MaximumGraphicsClipSize;
#endregion #endregion
#region Constructors #region Constructors
@ -66,6 +65,12 @@ namespace OpenTK.Graphics.Text
static GdiPlusGlyphRasterizer() static GdiPlusGlyphRasterizer()
{ {
default_string_format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces; default_string_format.FormatFlags |= StringFormatFlags.MeasureTrailingSpaces;
using (Bitmap bmp = new Bitmap(1, 1))
using (System.Drawing.Graphics gfx = System.Drawing.Graphics.FromImage(bmp))
{
MaximumGraphicsClipSize = gfx.ClipBounds.Size;
}
} }
public GdiPlusGlyphRasterizer() public GdiPlusGlyphRasterizer()
@ -79,11 +84,11 @@ namespace OpenTK.Graphics.Text
public Bitmap Rasterize(Glyph glyph) public Bitmap Rasterize(Glyph glyph)
{ {
RectangleF r = MeasureText( //RectangleF r = MeasureText(
new TextBlock( // new TextBlock(
glyph.Character.ToString(), glyph.Font, // glyph.Character.ToString(), glyph.Font,
TextPrinterOptions.NoCache, SizeF.Empty), // TextPrinterOptions.NoCache, SizeF.Empty),
PointF.Empty).BoundingBox; // PointF.Empty).BoundingBox;
EnsureSurfaceSize(ref glyph_surface, ref glyph_renderer, glyph.Font); EnsureSurfaceSize(ref glyph_surface, ref glyph_renderer, glyph.Font);
@ -183,11 +188,16 @@ namespace OpenTK.Graphics.Text
TextExtents MeasureTextExtents(TextBlock block, PointF location) TextExtents MeasureTextExtents(TextBlock block, PointF location)
{ {
// Todo: Parse layout options: // Todo: Parse layout options:
//StringFormat format = default_string_format;
StringFormat format = default_string_format; StringFormat format = default_string_format;
TextExtents extents = text_extents_pool.Acquire(); TextExtents extents = text_extents_pool.Acquire();
RectangleF rect = new RectangleF(location, block.Bounds); RectangleF rect = new RectangleF(location, block.Bounds);
// Work around Mono/GDI+ bug, which causes incorrect
// text wraping when block.Bounds == SizeF.Empty.
if (block.Bounds == SizeF.Empty)
rect.Size = MaximumGraphicsClipSize;
SetTextRenderingOptions(graphics, block.Font); SetTextRenderingOptions(graphics, block.Font);
@ -209,8 +219,7 @@ namespace OpenTK.Graphics.Text
foreach (string s in lines) foreach (string s in lines)
{ {
extents.AddRange(MeasureGlyphExtents( extents.AddRange(MeasureGlyphExtents(
s, height, 0, s.Length, s, height, rect,
rect,
native_graphics, native_font, native_string_format)); native_graphics, native_font, native_string_format));
height += block.Font.Height; height += block.Font.Height;
} }
@ -227,27 +236,24 @@ namespace OpenTK.Graphics.Text
// Gets the bounds of each character in a line of text. // Gets the bounds of each character in a line of text.
// The line is processed in blocks of 32 characters (GdiPlus.MaxMeasurableCharacterRanges). // The line is processed in blocks of 32 characters (GdiPlus.MaxMeasurableCharacterRanges).
IEnumerable<RectangleF> MeasureGlyphExtents(string text, int height, int line_start, int line_length, IEnumerable<RectangleF> MeasureGlyphExtents(string text, int height,
RectangleF layoutRect, IntPtr native_graphics, IntPtr native_font, IntPtr native_string_format) RectangleF layoutRect, IntPtr native_graphics, IntPtr native_font, IntPtr native_string_format)
{ {
RectangleF rect = new RectangleF(); RectangleF rect = new RectangleF();
int line_end = line_start + line_length; int current = 0;
while (line_start < line_end) while (current < text.Length)
{ {
//if (text[line_start] == '\n' || text[line_start] == '\r') int num_characters = (text.Length - current) > GdiPlus.MaxMeasurableCharacterRanges ?
//{
// line_start++;
// continue;
//}
int num_characters = (line_end - line_start) > GdiPlus.MaxMeasurableCharacterRanges ?
GdiPlus.MaxMeasurableCharacterRanges : GdiPlus.MaxMeasurableCharacterRanges :
line_end - line_start; text.Length - current;
int status = 0; int status = 0;
for (int i = 0; i < num_characters; i++) for (int i = 0; i < num_characters; i++)
{ {
characterRanges[i] = new CharacterRange(line_start + i, 1); if (text[current + i] == '\n' || text[current + i] == '\r')
throw new Exception();
characterRanges[i] = new CharacterRange(current + i, 1);
IntPtr region; IntPtr region;
status = GdiPlus.CreateRegion(out region); status = GdiPlus.CreateRegion(out region);
@ -274,7 +280,7 @@ namespace OpenTK.Graphics.Text
yield return rect; yield return rect;
} }
line_start += num_characters; current += num_characters;
} }
} }