This commit is contained in:
smallsql 2010-09-07 09:50:24 +00:00
Родитель c701a5fd6f
Коммит 14cd0fc9f9
2 изменённых файлов: 111 добавлений и 37 удалений

Просмотреть файл

@ -1,7 +1,7 @@
/* /*
Copyright (C) 2002, 2004, 2005, 2006, 2007 Jeroen Frijters Copyright (C) 2002, 2004, 2005, 2006, 2007 Jeroen Frijters
Copyright (C) 2006 Active Endpoints, Inc. Copyright (C) 2006 Active Endpoints, Inc.
Copyright (C) 2006, 2007, 2009 Volker Berlin Copyright (C) 2006, 2007, 2009, 2010 Volker Berlin
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -26,6 +26,8 @@
using System; using System;
using System.Drawing; using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Text; using System.Text;
using java.awt.font; using java.awt.font;
using java.awt.geom; using java.awt.geom;
@ -42,6 +44,16 @@ namespace ikvm.awt
class NetFontMetrics : java.awt.FontMetrics class NetFontMetrics : java.awt.FontMetrics
{ {
private static readonly Bitmap defaultbitmap = new Bitmap(1, 1);
private static readonly Graphics defaultGraphics = Graphics.FromImage(defaultbitmap);
static NetFontMetrics() {
defaultGraphics.SmoothingMode = SmoothingMode.None;
defaultGraphics.PixelOffsetMode = PixelOffsetMode.None;
defaultGraphics.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
}
public NetFontMetrics(java.awt.Font font) : base(font) public NetFontMetrics(java.awt.Font font) : base(font)
{ {
} }
@ -88,9 +100,9 @@ namespace ikvm.awt
return (int)Math.Round(GetDescentFloat()); return (int)Math.Round(GetDescentFloat());
} }
public override int stringWidth(string s) public override int stringWidth(string s)
{ {
return (int)Math.Round(GetStringBounds(s).getWidth()); return (int)Math.Round(GetStringWidth(s, defaultGraphics));
} }
public float GetAscentFloat() public float GetAscentFloat()
@ -113,45 +125,56 @@ namespace ikvm.awt
return Math.Max(0.0f, leading); return Math.Max(0.0f, leading);
} }
internal java.awt.geom.Rectangle2D GetStringBounds(String aString, System.Drawing.Graphics g) internal float GetStringWidth(String aString, System.Drawing.Graphics g) {
{ if (aString.Length == 0) {
// TODO (KR) Could replace with System.Windows.Forms.TextRenderer#MeasureText (to skip creating Graphics) return 0;
// } else {
// From .NET Framework Class Library documentation for Graphics#MeasureString: // System.Windows.Forms.TextRenderer#MeasureText seems to large
// // Graphics#MeasureString is many faster but work only correct with TextRenderingHint.AntiAlias
// To obtain metrics suitable for adjacent strings in layout (for StringFormat format;
// example, when implementing formatted text), use the switch (g.TextRenderingHint){
// MeasureCharacterRanges method or one of the MeasureString // Fractional metrics
// methods that takes a StringFormat, and pass GenericTypographic. case TextRenderingHint.AntiAlias:
// Also, ensure the TextRenderingHint for the Graphics is case TextRenderingHint.SingleBitPerPixel:
// AntiAlias. // this very mystic, if a StringFormat extends from GenericTypographic then the metric are different but like Java with fractional metrics
// format = new StringFormat(StringFormat.GenericTypographic);
// TODO (KR) Consider implementing with one of the Graphics#MeasureString methods that takes a StringFormat. break;
// TODO (KR) Consider implementing with Graphics#MeasureCharacterRanges(). default:
if (aString.Length == 0) format = new StringFormat();
{ break;
SizeF size = g.MeasureString(aString, GetNetFont(), Int32.MaxValue, StringFormat.GenericTypographic); }
return new java.awt.geom.Rectangle2D.Float(0, 0, size.Width, size.Height);
} format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap;
else
{
StringFormat format = new StringFormat(StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap);
format.Trimming = StringTrimming.None; format.Trimming = StringTrimming.None;
format.SetMeasurableCharacterRanges(new CharacterRange[] { new CharacterRange(0, aString.Length) }); format.SetMeasurableCharacterRanges(new CharacterRange[] { new CharacterRange(0, aString.Length) });
Region[] regions = g.MeasureCharacterRanges(aString, GetNetFont(), new RectangleF(0, 0, int.MaxValue, int.MaxValue), format); Region[] regions = g.MeasureCharacterRanges(aString, GetNetFont(), new RectangleF(0, 0, int.MaxValue, int.MaxValue), format);
SizeF size = regions[0].GetBounds(g).Size; SizeF size = regions[0].GetBounds(g).Size;
regions[0].Dispose(); regions[0].Dispose();
return new java.awt.geom.Rectangle2D.Float(0, -getAscent(), size.Width, size.Height); return size.Width;
} }
} }
internal java.awt.geom.Rectangle2D GetStringBounds(String aString, System.Drawing.Graphics g)
{
Font netFont = GetNetFont();
FontFamily family = netFont.FontFamily;
FontStyle style = netFont.Style;
float factor = netFont.Size / family.GetEmHeight(style);
float height = family.GetLineSpacing(style) * factor;
float descent = family.GetCellDescent(style) * factor;
float ascent = family.GetCellAscent(style) * factor;
float leading = height - ascent - descent;
return new java.awt.geom.Rectangle2D.Float(0, -ascent - leading / 2, GetStringWidth(aString, g), height);
}
public override java.awt.geom.Rectangle2D getStringBounds(String aString, java.awt.Graphics gr) public override java.awt.geom.Rectangle2D getStringBounds(String aString, java.awt.Graphics gr)
{ {
if (gr is NetGraphics) if (gr is NetGraphics)
{ {
return GetStringBounds(aString, ((NetGraphics)gr).JGraphics); return GetStringBounds(aString, ((NetGraphics)gr).JGraphics);
} }
return GetStringBounds(aString); return GetStringBounds(aString, defaultGraphics);
} }
internal java.awt.geom.Rectangle2D GetStringBounds(String aString) internal java.awt.geom.Rectangle2D GetStringBounds(String aString)

Просмотреть файл

@ -897,23 +897,64 @@ namespace ikvm.awt
} }
if (hintKey == java.awt.RenderingHints.KEY_TEXT_ANTIALIASING) if (hintKey == java.awt.RenderingHints.KEY_TEXT_ANTIALIASING)
{ {
if (hintValue == java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT) if (hintValue == java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT || hintValue == java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)
{ {
g.TextRenderingHint = TextRenderingHint.SystemDefault; switch (g.TextRenderingHint) {
return; case TextRenderingHint.SystemDefault:
} case TextRenderingHint.AntiAlias:
if (hintValue == java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF) g.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;
{ break;
g.TextRenderingHint = TextRenderingHint.SingleBitPerPixel; case TextRenderingHint.AntiAliasGridFit:
g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
break;
}
return; return;
} }
if (hintValue == java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON) if (hintValue == java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON)
{ {
g.TextRenderingHint = TextRenderingHint.AntiAlias; switch (g.TextRenderingHint) {
case TextRenderingHint.SystemDefault:
case TextRenderingHint.SingleBitPerPixel:
g.TextRenderingHint = TextRenderingHint.AntiAlias;
break;
case TextRenderingHint.SingleBitPerPixelGridFit:
g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
break;
}
return; return;
} }
return; return;
} }
if (hintKey == java.awt.RenderingHints.KEY_FRACTIONALMETRICS)
{
if (hintValue == java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT || hintValue == java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_OFF)
{
// OFF means enable GridFit
switch (g.TextRenderingHint) {
case TextRenderingHint.SystemDefault:
case TextRenderingHint.SingleBitPerPixel:
g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
break;
case TextRenderingHint.AntiAlias:
g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
break;
}
}
if (hintValue == java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_ON)
{
// ON means remove GridFit
switch (g.TextRenderingHint) {
case TextRenderingHint.SingleBitPerPixelGridFit:
g.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;
break;
case TextRenderingHint.AntiAliasGridFit:
case TextRenderingHint.ClearTypeGridFit:
g.TextRenderingHint = TextRenderingHint.AntiAlias;
break;
}
}
}
} }
public override object getRenderingHint(java.awt.RenderingHints.Key hintKey) public override object getRenderingHint(java.awt.RenderingHints.Key hintKey)
@ -972,14 +1013,24 @@ namespace ikvm.awt
{ {
case TextRenderingHint.SystemDefault: case TextRenderingHint.SystemDefault:
hints.put(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); hints.put(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT);
hints.put(java.awt.RenderingHints.KEY_FRACTIONALMETRICS, java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_DEFAULT);
break; break;
case TextRenderingHint.SingleBitPerPixelGridFit: case TextRenderingHint.SingleBitPerPixelGridFit:
hints.put(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
hints.put(java.awt.RenderingHints.KEY_FRACTIONALMETRICS, java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
break;
case TextRenderingHint.SingleBitPerPixel: case TextRenderingHint.SingleBitPerPixel:
hints.put(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); hints.put(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF);
hints.put(java.awt.RenderingHints.KEY_FRACTIONALMETRICS, java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_ON);
break; break;
case TextRenderingHint.AntiAlias: case TextRenderingHint.AntiAlias:
case TextRenderingHint.AntiAliasGridFit:
hints.put(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON); hints.put(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
hints.put(java.awt.RenderingHints.KEY_FRACTIONALMETRICS, java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_ON);
break;
case TextRenderingHint.AntiAliasGridFit:
case TextRenderingHint.ClearTypeGridFit:
hints.put(java.awt.RenderingHints.KEY_TEXT_ANTIALIASING, java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
hints.put(java.awt.RenderingHints.KEY_FRACTIONALMETRICS, java.awt.RenderingHints.VALUE_FRACTIONALMETRICS_OFF);
break; break;
} }
return hints; return hints;