Code:
/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / Misc / GDI / WindowsFont.cs / 1 / WindowsFont.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
#if WINFORMS_NAMESPACE
namespace System.Windows.Forms.Internal
#elif DRAWING_NAMESPACE
namespace System.Drawing.Internal
#else
namespace System.Experimental.Gdi
#endif
{
using System;
using System.Internal;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Text;
using System.Security;
using System.Security.Permissions;
using System.Globalization;
///
///
/// Encapsulates a GDI Font object.
///
///
#if WINFORMS_PUBLIC_GRAPHICS_LIBRARY
public
#else
internal
#endif
sealed partial class WindowsFont : MarshalByRefObject, ICloneable, IDisposable
{
const int LogFontNameOffset = 28;
// Handle to the native Windows font object.
//
private IntPtr hFont;
private float fontSize = -1.0f; //invalid value.
private int lineSpacing;
private bool ownHandle;
private bool ownedByCacheManager;
private bool everOwnedByCacheManager;
private IntNativeMethods.LOGFONT logFont;
private FontStyle style;
// Note: These defaults are according to the ones in GDI+ but those are not necessarily the same as the system
// default font. The GetSystemDefaultHFont() method should be used if needed.
private const string defaultFaceName = "Microsoft Sans Serif";
private const float defaultFontSize = 8.25f;
private const int defaultFontHeight = 13;
#if GDI_FINALIZATION_WATCH
private string AllocationSite = DbgUtil.StackTrace;
#endif
///
/// Creates the font handle.
///
private void CreateFont()
{
Debug.Assert( hFont == IntPtr.Zero, "hFont is not null, this will generate a handle leak." );
Debug.Assert( this.logFont != null, "WindowsFont.logFont not initialized." );
this.hFont = IntUnsafeNativeMethods.CreateFontIndirect(this.logFont);
#if TRACK_HFONT
Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "HFONT[0x{0:x8}] = CreateFontIndirect( LOGFONT={1} )", (int) this.hFont, this.logFont)));
#endif
if (this.hFont == IntPtr.Zero)
{
this.logFont.lfFaceName = defaultFaceName;
this.logFont.lfOutPrecision = IntNativeMethods.OUT_TT_ONLY_PRECIS; // True Type only.
this.hFont = IntUnsafeNativeMethods.CreateFontIndirect(this.logFont);
#if TRACK_HFONT
Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "HFONT[0x{0:x8}] = CreateFontIndirect( LOGFONT={1} )", (int) this.hFont, this.logFont)));
#endif
}
// Update logFont height and other adjusted parameters.
//
IntUnsafeNativeMethods.GetObject(new HandleRef(this, this.hFont), this.logFont);
// We created the hFont, we will delete it on dispose.
this.ownHandle = true;
}
/// Constructors.
///
/// Contructor to construct font from a face name.
/// >
public WindowsFont( string faceName ) :
this(faceName, defaultFontSize, FontStyle.Regular, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default)
{
// Default size in WinForms is 8.25f.
}
///
/// Contructor to construct font from a face name, a desired size and with the specified style.
/// >
public WindowsFont( string faceName, float size ) :
this(faceName, size, FontStyle.Regular, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default)
{
}
///
/// Contructor to construct font from a face name, a desired size and with the specified style.
/// >
public WindowsFont( string faceName, float size, FontStyle style ) :
this(faceName, size, style, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default)
{
}
///
/// Contructor to construct font from a face name, a desired size in points and with the specified style
/// and character set. The screen dc is used for calculating the font em height.
/// >
public WindowsFont( string faceName, float size, FontStyle style, byte charSet, WindowsFontQuality fontQuality )
{
Debug.Assert( size > 0.0f, "size has a negative value." );
const byte True = 1;
const byte False = 0;
this.logFont = new IntNativeMethods.LOGFONT();
//
// Get the font height from the specified size. size is in point units and height in logical
// units (pixels when using MM_TEXT) so we need to make the conversion using the number of
// pixels per logical inch along the screen height.
//
int pixelsY = (int) Math.Ceiling( WindowsGraphicsCacheManager.MeasurementGraphics.DeviceContext.DpiY * size / 72); // 1 point = 1/72 inch.;
//
// The lfHeight represents the font cell height (line spacing) which includes the internal
// leading; we specify a negative size value (in pixels) for the height so the font mapper
// provides the closest match for the character height rather than the cell height (MSDN).
//
this.logFont.lfHeight = -pixelsY;
this.logFont.lfFaceName = faceName != null ? faceName : defaultFaceName;
this.logFont.lfCharSet = charSet;
this.logFont.lfOutPrecision = IntNativeMethods.OUT_TT_PRECIS;
this.logFont.lfQuality = (byte) fontQuality;
this.logFont.lfWeight = (style & FontStyle.Bold) == FontStyle.Bold ? IntNativeMethods.FW_BOLD : IntNativeMethods.FW_NORMAL;
this.logFont.lfItalic = (style & FontStyle.Italic) == FontStyle.Italic ? True : False;
this.logFont.lfUnderline = (style & FontStyle.Underline) == FontStyle.Underline ? True : False;
this.logFont.lfStrikeOut = (style & FontStyle.Strikeout) == FontStyle.Strikeout ? True : False;
// Let the Size be recomputed to be consistent with the Height (there may be some precision loss coming from size to height).
// this.fontSize = size;
this.style = style;
CreateFont();
}
///
/// Contructor to construct font from a LOGFONT structure.
/// Pass false in the createHandle param to create a 'compatible' font (handle-less, to be used for measuring/comparing) or
/// when the handle has already been created.
///
private WindowsFont( IntNativeMethods.LOGFONT lf, bool createHandle )
{
Debug.Assert( lf != null, "lf is null" );
this.logFont = lf;
if (this.logFont.lfFaceName == null)
{
this.logFont.lfFaceName = defaultFaceName;
}
this.style = FontStyle.Regular;
if (lf.lfWeight == IntNativeMethods.FW_BOLD)
{
this.style |= FontStyle.Bold;
}
if (lf.lfItalic == 1)
{
this.style |= FontStyle.Italic;
}
if (lf.lfUnderline == 1)
{
this.style |= FontStyle.Underline;
}
if (lf.lfStrikeOut == 1)
{
this.style |= FontStyle.Strikeout;
}
if( createHandle )
{
CreateFont();
}
}
///
/// Contructs a WindowsFont object from an existing System.Drawing.Font object (GDI+), based on the screen dc MapMode
/// and resolution (normally: MM_TEXT and 96 dpi).
///
public static WindowsFont FromFont(Font font)
{
return FromFont(font, WindowsFontQuality.Default);
}
public static WindowsFont FromFont(Font font, WindowsFontQuality fontQuality)
{
string familyName = font.FontFamily.Name;
// Strip vertical-font mark from the name if needed.
if (familyName != null && familyName.Length > 1 && familyName[0] == '@')
{
familyName = familyName.Substring(1);
}
// Note: Creating the WindowsFont from Font using a LOGFONT structure from GDI+ (Font.ToLogFont(logFont)) may sound like
// a better choice (more accurate) for doing this but tests show that is not the case (see WindowsFontTests test suite),
// the results are the same. Also, that approach has some issues when the Font is created in a different application
// domain since the LOGFONT cannot be marshalled properly, see VSW#451960.
// Now, creating it using the Font.SizeInPoints makes it GraphicsUnit-independent.
return new WindowsFont(familyName, font.SizeInPoints, font.Style, font.GdiCharSet, fontQuality);
}
///
/// Creates a WindowsFont from the font selected in the supplied dc.
///
public static WindowsFont FromHdc( IntPtr hdc )
{
IntPtr hFont = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(null, hdc), IntNativeMethods.OBJ_FONT);
// don't call DeleteObject on handle from GetCurrentObject, it is the one selected in the hdc.
return FromHfont( hFont );
}
///
/// Creates a WindowsFont from the handle to a native GDI font. It does not take ownership of the
/// passed-in handle, the caller needs to delete the hFont when done with the WindowsFont.
///
public static WindowsFont FromHfont( IntPtr hFont )
{
return FromHfont( hFont, false );
}
///
/// Creates a WindowsFont from the handle to a native GDI font and optionally takes ownership of managing
/// the lifetime of the handle.
///
public static WindowsFont FromHfont( IntPtr hFont, bool takeOwnership )
{
IntNativeMethods.LOGFONT lf = new IntNativeMethods.LOGFONT();
IntUnsafeNativeMethods.GetObject(new HandleRef(null, hFont), lf);
WindowsFont wf = new WindowsFont( lf, /*createHandle*/ false );
wf.hFont = hFont;
wf.ownHandle = takeOwnership; // if true, hFont will be deleted on dispose.
return wf;
}
~WindowsFont()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
internal void Dispose(bool disposing)
{
bool deletedHandle = false;
if (this.ownHandle)
{
if (!ownedByCacheManager || !disposing) {
// If we were ever owned by the CacheManger and we're being disposed
// we can be sure that we're not in use by any DC's (otherwise Dispose() wouldn't have been called)
// skip the check IsFontInUse check in this case.
// Also skip the check if disposing == false, because the cache is thread-static
// and that means we're being called from the finalizer.
if (everOwnedByCacheManager || !disposing || !DeviceContexts.IsFontInUse(this)) {
Debug.Assert( this.hFont != IntPtr.Zero, "Unexpected null hFont." );
DbgUtil.AssertFinalization(this, disposing);
IntUnsafeNativeMethods.DeleteObject(new HandleRef(this, this.hFont));
#if TRACK_HFONT
Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "DeleteObject(HFONT[0x{0:x8}]))", (int) this.hFont)));
#endif
this.hFont = IntPtr.Zero;
this.ownHandle = false;
deletedHandle = true;
}
}
}
if (disposing && (deletedHandle || !ownHandle))
{
GC.SuppressFinalize(this);
}
}
///
/// Returns a value indicating whether the specified object is a WindowsFont equivalent to this object.
///
public override bool Equals( object font )
{
WindowsFont winFont = font as WindowsFont;
if( winFont == null )
{
return false;
}
if( winFont == this )
{
return true;
}
// WARNING: don't use non-public fields/properties here, the passed-in font object could be a proxy in a
// remoting scenario and proxies cannot access internal or private members. VSW#465265 & 465647
// Compare params used to create the font.
return this.Name == winFont.Name &&
this.LogFontHeight == winFont.LogFontHeight && // Equivalent to comparing Size but always at hand.
this.Style == winFont.Style &&
this.CharSet == winFont.CharSet &&
this.Quality == winFont.Quality;
}
///
/// Gets the hash code for this WindowsFont.
///
public override int GetHashCode()
{
// similar to Font.GetHashCode().
return (int)((((UInt32)this.Style << 13) | ((UInt32)this.Style >> 19)) ^
(((UInt32)this.CharSet << 26) | ((UInt32)this.CharSet >> 6)) ^
(((UInt32)this.Size << 7) | ((UInt32)this.Size >> 25)));
}
///
/// Clones this object.
///
public object Clone()
{
return new WindowsFont( this.logFont, true );
}
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "[{0}: Name={1}, Size={2} points, Height={3} pixels, Sytle={4}]", GetType().Name, logFont.lfFaceName, this.Size, this.Height, this.Style);
}
////////////////////////////////////////////
/// Properties
///
/// Returns this object's native Win32 font handle. Should NOT be deleted externally.
/// Compare with ToHfont method.
///
public IntPtr Hfont
{
get
{
//Assert removed. We need to be able to check for Hfont == IntPtr.Zero to determine if the object was disposed.
//Debug.Assert(this.hFont != IntPtr.Zero, "hFont is null, are you using a disposed object?");
return this.hFont;
}
}
///
/// Determines whether the font has the italic style or not.
///
public bool Italic
{
get
{
return logFont.lfItalic == 1;
}
}
public bool OwnedByCacheManager
{
get {
return ownedByCacheManager;
}
set {
if (value) {
everOwnedByCacheManager = true;
}
ownedByCacheManager = value;
}
}
///
/// Rendering quality.
///
public WindowsFontQuality Quality
{
get
{
return (WindowsFontQuality) this.logFont.lfQuality;
}
}
///
/// Gets the font style.
///
public FontStyle Style
{
get
{
return this.style;
}
}
///
/// Gets the line spacing (cell height) of this font in (screen) pixels using the screen resolution.
/// Gets the line spacing (cell height), in pixels (using the screen DC resolution), of this font.
/// The line spacing is the vertical distance between the base lines of two consecutive lines of text.
/// Thus, the line spacing includes the blank space between lines along with the height of the character
/// itself.
///
public int Height
{
//
get
{
if( this.lineSpacing == 0 )
{
// Observe that the font text metrics are obtained using the resolution of the screen.
WindowsGraphics wg = WindowsGraphicsCacheManager.MeasurementGraphics;
// No need to reset the font (if changed) since we always set the font before using the MeasurementGraphics
// in WindowsGraphics methods.
wg.DeviceContext.SelectFont(this);
IntNativeMethods.TEXTMETRIC tm = (IntNativeMethods.TEXTMETRIC) wg.GetTextMetrics();
this.lineSpacing = tm.tmHeight;
}
return this.lineSpacing;
}
}
///
/// Gets the font character set.
/// This is used by the system font mapper when searching for the physical font that best matches the logical font.
///
public byte CharSet
{
get
{
return logFont.lfCharSet;
}
}
///
/// Specifies the height, in logical units, of the font's character cell or character. The character height value (em height)
/// is the character cell height value minus the internal-leading value.
///
public int LogFontHeight
{
get
{
return logFont.lfHeight;
}
}
///
/// The font's face name.
///
public string Name
{
get
{
return logFont.lfFaceName;
}
}
///
/// Gets the character height (as opposed to the cell height) of the font represented by this object in points.
/// Consider
///
public float Size
{
get
{
if( this.fontSize < 0.0f )
{
WindowsGraphics wg = WindowsGraphicsCacheManager.MeasurementGraphics;
// No need to reset the font (if changed) since we always set the font before using the MeasurementGraphics
// in WindowsGraphics methods.
wg.DeviceContext.SelectFont(this);
IntNativeMethods.TEXTMETRIC tm = (IntNativeMethods.TEXTMETRIC) wg.GetTextMetrics();
//
// Convert the font character height to points. If lfHeight is negative, Windows
// treats the absolute value of that number as a desired font height compatible with
// the point size; in this case lfHeight will roughly match the tmHeight field of
// the TEXTMETRIC structure less the tmInternalLeading field.
//
int height = this.logFont.lfHeight > 0 ? tm.tmHeight : (tm.tmHeight - tm.tmInternalLeading);
//
/*
switch (this.unit)
{
case GraphicsUnit.Pixel: worldEmSize = height * dpi / 72.0f; break;
case GraphicsUnit.Point: worldEmSize = height * dpi / 72.0f; break;
case GraphicsUnit.Inch: worldEmSize = height * dpi; break;
case GraphicsUnit.Document: worldEmSize = height * dpi / 300.0f; break;
case GraphicsUnit.Millimeter: worldEmSize = height * dpi / 25.4f; break;
}
*/
this.fontSize = height * 72f / wg.DeviceContext.DpiY;
}
return this.fontSize;
}
}
///
/// Attempts to match the TextRenderingHint of the specified Graphics object with a LOGFONT.lfQuality value.
///
public static WindowsFontQuality WindowsFontQualityFromTextRenderingHint(Graphics g)
{
if (g == null)
{
return WindowsFontQuality.Default;
}
switch (g.TextRenderingHint)
{
case TextRenderingHint.ClearTypeGridFit:
// See WindowsFontQuality enum for the flags supported in the different OS systems.
if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1)
{
return WindowsFontQuality.ClearTypeNatural;
}
else
{
return WindowsFontQuality.ClearType;
}
case TextRenderingHint.AntiAliasGridFit:
return WindowsFontQuality.AntiAliased;
case TextRenderingHint.AntiAlias:
return WindowsFontQuality.AntiAliased;
case TextRenderingHint.SingleBitPerPixelGridFit:
return WindowsFontQuality.Proof;
case TextRenderingHint.SingleBitPerPixel:
return WindowsFontQuality.Draft;
default:
case TextRenderingHint.SystemDefault:
return WindowsFontQuality.Default;
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
#if WINFORMS_NAMESPACE
namespace System.Windows.Forms.Internal
#elif DRAWING_NAMESPACE
namespace System.Drawing.Internal
#else
namespace System.Experimental.Gdi
#endif
{
using System;
using System.Internal;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Text;
using System.Security;
using System.Security.Permissions;
using System.Globalization;
///
///
/// Encapsulates a GDI Font object.
///
///
#if WINFORMS_PUBLIC_GRAPHICS_LIBRARY
public
#else
internal
#endif
sealed partial class WindowsFont : MarshalByRefObject, ICloneable, IDisposable
{
const int LogFontNameOffset = 28;
// Handle to the native Windows font object.
//
private IntPtr hFont;
private float fontSize = -1.0f; //invalid value.
private int lineSpacing;
private bool ownHandle;
private bool ownedByCacheManager;
private bool everOwnedByCacheManager;
private IntNativeMethods.LOGFONT logFont;
private FontStyle style;
// Note: These defaults are according to the ones in GDI+ but those are not necessarily the same as the system
// default font. The GetSystemDefaultHFont() method should be used if needed.
private const string defaultFaceName = "Microsoft Sans Serif";
private const float defaultFontSize = 8.25f;
private const int defaultFontHeight = 13;
#if GDI_FINALIZATION_WATCH
private string AllocationSite = DbgUtil.StackTrace;
#endif
///
/// Creates the font handle.
///
private void CreateFont()
{
Debug.Assert( hFont == IntPtr.Zero, "hFont is not null, this will generate a handle leak." );
Debug.Assert( this.logFont != null, "WindowsFont.logFont not initialized." );
this.hFont = IntUnsafeNativeMethods.CreateFontIndirect(this.logFont);
#if TRACK_HFONT
Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "HFONT[0x{0:x8}] = CreateFontIndirect( LOGFONT={1} )", (int) this.hFont, this.logFont)));
#endif
if (this.hFont == IntPtr.Zero)
{
this.logFont.lfFaceName = defaultFaceName;
this.logFont.lfOutPrecision = IntNativeMethods.OUT_TT_ONLY_PRECIS; // True Type only.
this.hFont = IntUnsafeNativeMethods.CreateFontIndirect(this.logFont);
#if TRACK_HFONT
Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "HFONT[0x{0:x8}] = CreateFontIndirect( LOGFONT={1} )", (int) this.hFont, this.logFont)));
#endif
}
// Update logFont height and other adjusted parameters.
//
IntUnsafeNativeMethods.GetObject(new HandleRef(this, this.hFont), this.logFont);
// We created the hFont, we will delete it on dispose.
this.ownHandle = true;
}
/// Constructors.
///
/// Contructor to construct font from a face name.
/// >
public WindowsFont( string faceName ) :
this(faceName, defaultFontSize, FontStyle.Regular, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default)
{
// Default size in WinForms is 8.25f.
}
///
/// Contructor to construct font from a face name, a desired size and with the specified style.
/// >
public WindowsFont( string faceName, float size ) :
this(faceName, size, FontStyle.Regular, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default)
{
}
///
/// Contructor to construct font from a face name, a desired size and with the specified style.
/// >
public WindowsFont( string faceName, float size, FontStyle style ) :
this(faceName, size, style, IntNativeMethods.DEFAULT_CHARSET, WindowsFontQuality.Default)
{
}
///
/// Contructor to construct font from a face name, a desired size in points and with the specified style
/// and character set. The screen dc is used for calculating the font em height.
/// >
public WindowsFont( string faceName, float size, FontStyle style, byte charSet, WindowsFontQuality fontQuality )
{
Debug.Assert( size > 0.0f, "size has a negative value." );
const byte True = 1;
const byte False = 0;
this.logFont = new IntNativeMethods.LOGFONT();
//
// Get the font height from the specified size. size is in point units and height in logical
// units (pixels when using MM_TEXT) so we need to make the conversion using the number of
// pixels per logical inch along the screen height.
//
int pixelsY = (int) Math.Ceiling( WindowsGraphicsCacheManager.MeasurementGraphics.DeviceContext.DpiY * size / 72); // 1 point = 1/72 inch.;
//
// The lfHeight represents the font cell height (line spacing) which includes the internal
// leading; we specify a negative size value (in pixels) for the height so the font mapper
// provides the closest match for the character height rather than the cell height (MSDN).
//
this.logFont.lfHeight = -pixelsY;
this.logFont.lfFaceName = faceName != null ? faceName : defaultFaceName;
this.logFont.lfCharSet = charSet;
this.logFont.lfOutPrecision = IntNativeMethods.OUT_TT_PRECIS;
this.logFont.lfQuality = (byte) fontQuality;
this.logFont.lfWeight = (style & FontStyle.Bold) == FontStyle.Bold ? IntNativeMethods.FW_BOLD : IntNativeMethods.FW_NORMAL;
this.logFont.lfItalic = (style & FontStyle.Italic) == FontStyle.Italic ? True : False;
this.logFont.lfUnderline = (style & FontStyle.Underline) == FontStyle.Underline ? True : False;
this.logFont.lfStrikeOut = (style & FontStyle.Strikeout) == FontStyle.Strikeout ? True : False;
// Let the Size be recomputed to be consistent with the Height (there may be some precision loss coming from size to height).
// this.fontSize = size;
this.style = style;
CreateFont();
}
///
/// Contructor to construct font from a LOGFONT structure.
/// Pass false in the createHandle param to create a 'compatible' font (handle-less, to be used for measuring/comparing) or
/// when the handle has already been created.
///
private WindowsFont( IntNativeMethods.LOGFONT lf, bool createHandle )
{
Debug.Assert( lf != null, "lf is null" );
this.logFont = lf;
if (this.logFont.lfFaceName == null)
{
this.logFont.lfFaceName = defaultFaceName;
}
this.style = FontStyle.Regular;
if (lf.lfWeight == IntNativeMethods.FW_BOLD)
{
this.style |= FontStyle.Bold;
}
if (lf.lfItalic == 1)
{
this.style |= FontStyle.Italic;
}
if (lf.lfUnderline == 1)
{
this.style |= FontStyle.Underline;
}
if (lf.lfStrikeOut == 1)
{
this.style |= FontStyle.Strikeout;
}
if( createHandle )
{
CreateFont();
}
}
///
/// Contructs a WindowsFont object from an existing System.Drawing.Font object (GDI+), based on the screen dc MapMode
/// and resolution (normally: MM_TEXT and 96 dpi).
///
public static WindowsFont FromFont(Font font)
{
return FromFont(font, WindowsFontQuality.Default);
}
public static WindowsFont FromFont(Font font, WindowsFontQuality fontQuality)
{
string familyName = font.FontFamily.Name;
// Strip vertical-font mark from the name if needed.
if (familyName != null && familyName.Length > 1 && familyName[0] == '@')
{
familyName = familyName.Substring(1);
}
// Note: Creating the WindowsFont from Font using a LOGFONT structure from GDI+ (Font.ToLogFont(logFont)) may sound like
// a better choice (more accurate) for doing this but tests show that is not the case (see WindowsFontTests test suite),
// the results are the same. Also, that approach has some issues when the Font is created in a different application
// domain since the LOGFONT cannot be marshalled properly, see VSW#451960.
// Now, creating it using the Font.SizeInPoints makes it GraphicsUnit-independent.
return new WindowsFont(familyName, font.SizeInPoints, font.Style, font.GdiCharSet, fontQuality);
}
///
/// Creates a WindowsFont from the font selected in the supplied dc.
///
public static WindowsFont FromHdc( IntPtr hdc )
{
IntPtr hFont = IntUnsafeNativeMethods.GetCurrentObject(new HandleRef(null, hdc), IntNativeMethods.OBJ_FONT);
// don't call DeleteObject on handle from GetCurrentObject, it is the one selected in the hdc.
return FromHfont( hFont );
}
///
/// Creates a WindowsFont from the handle to a native GDI font. It does not take ownership of the
/// passed-in handle, the caller needs to delete the hFont when done with the WindowsFont.
///
public static WindowsFont FromHfont( IntPtr hFont )
{
return FromHfont( hFont, false );
}
///
/// Creates a WindowsFont from the handle to a native GDI font and optionally takes ownership of managing
/// the lifetime of the handle.
///
public static WindowsFont FromHfont( IntPtr hFont, bool takeOwnership )
{
IntNativeMethods.LOGFONT lf = new IntNativeMethods.LOGFONT();
IntUnsafeNativeMethods.GetObject(new HandleRef(null, hFont), lf);
WindowsFont wf = new WindowsFont( lf, /*createHandle*/ false );
wf.hFont = hFont;
wf.ownHandle = takeOwnership; // if true, hFont will be deleted on dispose.
return wf;
}
~WindowsFont()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
internal void Dispose(bool disposing)
{
bool deletedHandle = false;
if (this.ownHandle)
{
if (!ownedByCacheManager || !disposing) {
// If we were ever owned by the CacheManger and we're being disposed
// we can be sure that we're not in use by any DC's (otherwise Dispose() wouldn't have been called)
// skip the check IsFontInUse check in this case.
// Also skip the check if disposing == false, because the cache is thread-static
// and that means we're being called from the finalizer.
if (everOwnedByCacheManager || !disposing || !DeviceContexts.IsFontInUse(this)) {
Debug.Assert( this.hFont != IntPtr.Zero, "Unexpected null hFont." );
DbgUtil.AssertFinalization(this, disposing);
IntUnsafeNativeMethods.DeleteObject(new HandleRef(this, this.hFont));
#if TRACK_HFONT
Debug.WriteLine( DbgUtil.StackTraceToStr(String.Format( "DeleteObject(HFONT[0x{0:x8}]))", (int) this.hFont)));
#endif
this.hFont = IntPtr.Zero;
this.ownHandle = false;
deletedHandle = true;
}
}
}
if (disposing && (deletedHandle || !ownHandle))
{
GC.SuppressFinalize(this);
}
}
///
/// Returns a value indicating whether the specified object is a WindowsFont equivalent to this object.
///
public override bool Equals( object font )
{
WindowsFont winFont = font as WindowsFont;
if( winFont == null )
{
return false;
}
if( winFont == this )
{
return true;
}
// WARNING: don't use non-public fields/properties here, the passed-in font object could be a proxy in a
// remoting scenario and proxies cannot access internal or private members. VSW#465265 & 465647
// Compare params used to create the font.
return this.Name == winFont.Name &&
this.LogFontHeight == winFont.LogFontHeight && // Equivalent to comparing Size but always at hand.
this.Style == winFont.Style &&
this.CharSet == winFont.CharSet &&
this.Quality == winFont.Quality;
}
///
/// Gets the hash code for this WindowsFont.
///
public override int GetHashCode()
{
// similar to Font.GetHashCode().
return (int)((((UInt32)this.Style << 13) | ((UInt32)this.Style >> 19)) ^
(((UInt32)this.CharSet << 26) | ((UInt32)this.CharSet >> 6)) ^
(((UInt32)this.Size << 7) | ((UInt32)this.Size >> 25)));
}
///
/// Clones this object.
///
public object Clone()
{
return new WindowsFont( this.logFont, true );
}
public override string ToString()
{
return string.Format(CultureInfo.CurrentCulture, "[{0}: Name={1}, Size={2} points, Height={3} pixels, Sytle={4}]", GetType().Name, logFont.lfFaceName, this.Size, this.Height, this.Style);
}
////////////////////////////////////////////
/// Properties
///
/// Returns this object's native Win32 font handle. Should NOT be deleted externally.
/// Compare with ToHfont method.
///
public IntPtr Hfont
{
get
{
//Assert removed. We need to be able to check for Hfont == IntPtr.Zero to determine if the object was disposed.
//Debug.Assert(this.hFont != IntPtr.Zero, "hFont is null, are you using a disposed object?");
return this.hFont;
}
}
///
/// Determines whether the font has the italic style or not.
///
public bool Italic
{
get
{
return logFont.lfItalic == 1;
}
}
public bool OwnedByCacheManager
{
get {
return ownedByCacheManager;
}
set {
if (value) {
everOwnedByCacheManager = true;
}
ownedByCacheManager = value;
}
}
///
/// Rendering quality.
///
public WindowsFontQuality Quality
{
get
{
return (WindowsFontQuality) this.logFont.lfQuality;
}
}
///
/// Gets the font style.
///
public FontStyle Style
{
get
{
return this.style;
}
}
///
/// Gets the line spacing (cell height) of this font in (screen) pixels using the screen resolution.
/// Gets the line spacing (cell height), in pixels (using the screen DC resolution), of this font.
/// The line spacing is the vertical distance between the base lines of two consecutive lines of text.
/// Thus, the line spacing includes the blank space between lines along with the height of the character
/// itself.
///
public int Height
{
//
get
{
if( this.lineSpacing == 0 )
{
// Observe that the font text metrics are obtained using the resolution of the screen.
WindowsGraphics wg = WindowsGraphicsCacheManager.MeasurementGraphics;
// No need to reset the font (if changed) since we always set the font before using the MeasurementGraphics
// in WindowsGraphics methods.
wg.DeviceContext.SelectFont(this);
IntNativeMethods.TEXTMETRIC tm = (IntNativeMethods.TEXTMETRIC) wg.GetTextMetrics();
this.lineSpacing = tm.tmHeight;
}
return this.lineSpacing;
}
}
///
/// Gets the font character set.
/// This is used by the system font mapper when searching for the physical font that best matches the logical font.
///
public byte CharSet
{
get
{
return logFont.lfCharSet;
}
}
///
/// Specifies the height, in logical units, of the font's character cell or character. The character height value (em height)
/// is the character cell height value minus the internal-leading value.
///
public int LogFontHeight
{
get
{
return logFont.lfHeight;
}
}
///
/// The font's face name.
///
public string Name
{
get
{
return logFont.lfFaceName;
}
}
///
/// Gets the character height (as opposed to the cell height) of the font represented by this object in points.
/// Consider
///
public float Size
{
get
{
if( this.fontSize < 0.0f )
{
WindowsGraphics wg = WindowsGraphicsCacheManager.MeasurementGraphics;
// No need to reset the font (if changed) since we always set the font before using the MeasurementGraphics
// in WindowsGraphics methods.
wg.DeviceContext.SelectFont(this);
IntNativeMethods.TEXTMETRIC tm = (IntNativeMethods.TEXTMETRIC) wg.GetTextMetrics();
//
// Convert the font character height to points. If lfHeight is negative, Windows
// treats the absolute value of that number as a desired font height compatible with
// the point size; in this case lfHeight will roughly match the tmHeight field of
// the TEXTMETRIC structure less the tmInternalLeading field.
//
int height = this.logFont.lfHeight > 0 ? tm.tmHeight : (tm.tmHeight - tm.tmInternalLeading);
//
/*
switch (this.unit)
{
case GraphicsUnit.Pixel: worldEmSize = height * dpi / 72.0f; break;
case GraphicsUnit.Point: worldEmSize = height * dpi / 72.0f; break;
case GraphicsUnit.Inch: worldEmSize = height * dpi; break;
case GraphicsUnit.Document: worldEmSize = height * dpi / 300.0f; break;
case GraphicsUnit.Millimeter: worldEmSize = height * dpi / 25.4f; break;
}
*/
this.fontSize = height * 72f / wg.DeviceContext.DpiY;
}
return this.fontSize;
}
}
///
/// Attempts to match the TextRenderingHint of the specified Graphics object with a LOGFONT.lfQuality value.
///
public static WindowsFontQuality WindowsFontQualityFromTextRenderingHint(Graphics g)
{
if (g == null)
{
return WindowsFontQuality.Default;
}
switch (g.TextRenderingHint)
{
case TextRenderingHint.ClearTypeGridFit:
// See WindowsFontQuality enum for the flags supported in the different OS systems.
if (Environment.OSVersion.Version.Major == 5 && Environment.OSVersion.Version.Minor >= 1)
{
return WindowsFontQuality.ClearTypeNatural;
}
else
{
return WindowsFontQuality.ClearType;
}
case TextRenderingHint.AntiAliasGridFit:
return WindowsFontQuality.AntiAliased;
case TextRenderingHint.AntiAlias:
return WindowsFontQuality.AntiAliased;
case TextRenderingHint.SingleBitPerPixelGridFit:
return WindowsFontQuality.Proof;
case TextRenderingHint.SingleBitPerPixel:
return WindowsFontQuality.Draft;
default:
case TextRenderingHint.SystemDefault:
return WindowsFontQuality.Default;
}
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- PerformanceCounterPermissionEntryCollection.cs
- Descriptor.cs
- VisualBasicExpressionConverter.cs
- WindowClosedEventArgs.cs
- ToolStripComboBox.cs
- CmsInterop.cs
- BufferedReadStream.cs
- EntityDataReader.cs
- RuleConditionDialog.Designer.cs
- AttachedAnnotation.cs
- EntityDesignerUtils.cs
- Crc32Helper.cs
- loginstatus.cs
- ColumnResult.cs
- LeaseManager.cs
- CommonDialog.cs
- SystemNetHelpers.cs
- Types.cs
- SqlInternalConnectionSmi.cs
- HttpCacheVary.cs
- SQLDateTimeStorage.cs
- AuthorizationRule.cs
- UIElement3D.cs
- LogWriteRestartAreaState.cs
- CfgArc.cs
- RtfControlWordInfo.cs
- EntryPointNotFoundException.cs
- ModuleBuilderData.cs
- AsymmetricSignatureDeformatter.cs
- StylusEventArgs.cs
- ZipIOModeEnforcingStream.cs
- SharedPersonalizationStateInfo.cs
- StreamingContext.cs
- Win32SafeHandles.cs
- ArgumentsParser.cs
- CreateInstanceBinder.cs
- LinkedDataMemberFieldEditor.cs
- pingexception.cs
- XPathNode.cs
- HiddenFieldPageStatePersister.cs
- InvalidCastException.cs
- CrossContextChannel.cs
- CodeTypeReferenceExpression.cs
- AuthenticateEventArgs.cs
- RoutedEventValueSerializer.cs
- FacetChecker.cs
- SourceItem.cs
- TextEmbeddedObject.cs
- InvokeDelegate.cs
- ScalarConstant.cs
- TypeExtension.cs
- AttributeProviderAttribute.cs
- TaskFormBase.cs
- IIS7UserPrincipal.cs
- AppearanceEditorPart.cs
- DeviceFilterEditorDialog.cs
- KeysConverter.cs
- JournalEntryListConverter.cs
- DataGridViewBindingCompleteEventArgs.cs
- ACL.cs
- XmlNamedNodeMap.cs
- EncoderParameters.cs
- RemotingServices.cs
- SynchronizationContext.cs
- PolicyImporterElementCollection.cs
- SchemaExporter.cs
- TextEndOfParagraph.cs
- DataGridColumnFloatingHeader.cs
- RelationshipWrapper.cs
- Popup.cs
- SerialErrors.cs
- FragmentNavigationEventArgs.cs
- EncryptedKeyIdentifierClause.cs
- NullableIntAverageAggregationOperator.cs
- WindowsTab.cs
- CodeDirectiveCollection.cs
- CodeTypeDeclarationCollection.cs
- CompoundFileDeflateTransform.cs
- GacUtil.cs
- InvalidAsynchronousStateException.cs
- StateItem.cs
- RelationshipConverter.cs
- ProgressPage.cs
- ParameterCollection.cs
- GroupBox.cs
- ProxyAttribute.cs
- TraceProvider.cs
- RecognizedWordUnit.cs
- FieldToken.cs
- OutOfProcStateClientManager.cs
- EdmItemError.cs
- FileLogRecordStream.cs
- SqlFactory.cs
- PrinterResolution.cs
- QilLiteral.cs
- ListParaClient.cs
- _ListenerResponseStream.cs
- OneOfTypeConst.cs
- ADMembershipUser.cs
- PartialCachingControl.cs