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) 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
warranty. In no event will the authors be held liable for any damages
@ -26,6 +26,8 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Text;
using java.awt.font;
using java.awt.geom;
@ -42,6 +44,16 @@ namespace ikvm.awt
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)
{
}
@ -88,9 +100,9 @@ namespace ikvm.awt
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()
@ -113,45 +125,56 @@ namespace ikvm.awt
return Math.Max(0.0f, leading);
}
internal java.awt.geom.Rectangle2D GetStringBounds(String aString, System.Drawing.Graphics g)
{
// TODO (KR) Could replace with System.Windows.Forms.TextRenderer#MeasureText (to skip creating Graphics)
//
// From .NET Framework Class Library documentation for Graphics#MeasureString:
//
// To obtain metrics suitable for adjacent strings in layout (for
// example, when implementing formatted text), use the
// MeasureCharacterRanges method or one of the MeasureString
// methods that takes a StringFormat, and pass GenericTypographic.
// Also, ensure the TextRenderingHint for the Graphics is
// AntiAlias.
//
// TODO (KR) Consider implementing with one of the Graphics#MeasureString methods that takes a StringFormat.
// TODO (KR) Consider implementing with Graphics#MeasureCharacterRanges().
if (aString.Length == 0)
{
SizeF size = g.MeasureString(aString, GetNetFont(), Int32.MaxValue, StringFormat.GenericTypographic);
return new java.awt.geom.Rectangle2D.Float(0, 0, size.Width, size.Height);
}
else
{
StringFormat format = new StringFormat(StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap);
internal float GetStringWidth(String aString, System.Drawing.Graphics g) {
if (aString.Length == 0) {
return 0;
} else {
// System.Windows.Forms.TextRenderer#MeasureText seems to large
// Graphics#MeasureString is many faster but work only correct with TextRenderingHint.AntiAlias
StringFormat format;
switch (g.TextRenderingHint){
// Fractional metrics
case TextRenderingHint.AntiAlias:
case TextRenderingHint.SingleBitPerPixel:
// 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);
break;
default:
format = new StringFormat();
break;
}
format.FormatFlags = StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap;
format.Trimming = StringTrimming.None;
format.SetMeasurableCharacterRanges(new CharacterRange[] { new CharacterRange(0, aString.Length) });
Region[] regions = g.MeasureCharacterRanges(aString, GetNetFont(), new RectangleF(0, 0, int.MaxValue, int.MaxValue), format);
SizeF size = regions[0].GetBounds(g).Size;
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)
{
if (gr is NetGraphics)
{
return GetStringBounds(aString, ((NetGraphics)gr).JGraphics);
}
return GetStringBounds(aString);
return GetStringBounds(aString, defaultGraphics);
}
internal java.awt.geom.Rectangle2D GetStringBounds(String aString)

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

@ -897,23 +897,64 @@ namespace ikvm.awt
}
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;
return;
}
if (hintValue == java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_OFF)
{
g.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;
switch (g.TextRenderingHint) {
case TextRenderingHint.SystemDefault:
case TextRenderingHint.AntiAlias:
g.TextRenderingHint = TextRenderingHint.SingleBitPerPixel;
break;
case TextRenderingHint.AntiAliasGridFit:
g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit;
break;
}
return;
}
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;
}
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)
@ -972,14 +1013,24 @@ namespace ikvm.awt
{
case TextRenderingHint.SystemDefault:
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;
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:
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;
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_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;
}
return hints;