I have searched a lot and tried much but I can not find the proper solution.
I wonder is there any approach for determining exact glyph height in specified font?
I mean here when I want to determine the height of DOT glyph I should receive small height but not height with paddings or the font size.
I have found the solution for determining exact glyph width here (I have used the second approach) but it does not work for height.
UPDATE: I need solution for .NET 1.1
The easy way to know what is in a font's character set is by viewing the software's glyph panel. For any font, begin by selecting the Entire Font option. From there, view the submenus, investigating categories of glyphs you might be interested in. (These categories closely mirror those in the OpenType panel.)
A glyph is a single representation of a character. Every font has a Unicode character map that links (abstract) character IDs with how to display that character, using the default glyphs.
Hold Shift and press Return or double-click on the selection to create glyphs for all selected cells. Hold Shift and select the Font > Generate Glyphs menu command. See Generate Glyphs for details. Select the Font > Add Glyphs menu command to add several Unicode glyphs at once.
A glyph is a specific form of a character. For example, in certain fonts, the capital letter A is available in several forms, such as swash and small cap. You can use the Glyphs panel to locate any glyph in a font. OpenType fonts such as Adobe Caslon™ Pro provide multiple glyphs for many standard characters.
It's not that hard to get the character metrics. GDI contains a function GetGlyphOutline
that you can call with the GGO_METRICS
constant to get the height and width of the smallest enclosing rectangle required to contain the glyph when rendered. I.e, a 10 point glyph for a dot in font Arial will give a rectangle of 1x1 pixels, and for the letter I 95x.14 if the font is 100 points in size.
These are the declaration for the P/Invoke calls:
// the declarations
public struct FIXED
{
public short fract;
public short value;
}
public struct MAT2
{
[MarshalAs(UnmanagedType.Struct)] public FIXED eM11;
[MarshalAs(UnmanagedType.Struct)] public FIXED eM12;
[MarshalAs(UnmanagedType.Struct)] public FIXED eM21;
[MarshalAs(UnmanagedType.Struct)] public FIXED eM22;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINTFX
{
[MarshalAs(UnmanagedType.Struct)] public FIXED x;
[MarshalAs(UnmanagedType.Struct)] public FIXED y;
}
[StructLayout(LayoutKind.Sequential)]
public struct GLYPHMETRICS
{
public int gmBlackBoxX;
public int gmBlackBoxY;
[MarshalAs(UnmanagedType.Struct)] public POINT gmptGlyphOrigin;
[MarshalAs(UnmanagedType.Struct)] public POINTFX gmptfxGlyphOrigin;
public short gmCellIncX;
public short gmCellIncY;
}
private const int GGO_METRICS = 0;
private const uint GDI_ERROR = 0xFFFFFFFF;
[DllImport("gdi32.dll")]
static extern uint GetGlyphOutline(IntPtr hdc, uint uChar, uint uFormat,
out GLYPHMETRICS lpgm, uint cbBuffer, IntPtr lpvBuffer, ref MAT2 lpmat2);
[DllImport("gdi32.dll", ExactSpelling = true, PreserveSig = true, SetLastError = true)]
static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);
The actual code, rather trivial, if you don't consider the P/Invoke redundancies. I tested the code, it works (you can adjust for getting the width as well from GLYPHMETRICS
).
Note: this is ad-hoc code, in the real world, you should clean up the HDC's and objects with ReleaseHandle
and DeleteObject
. Thanks to a comment by user2173353 to point this out.
// if you want exact metrics, use a high font size and divide the result
// otherwise, the resulting rectangle is rounded to nearest int
private int GetGlyphHeight(char letter, string fontName, float fontPointSize)
{
// init the font. Probably better to do this outside this function for performance
Font font = new Font(new FontFamily(fontName), fontPointSize);
GLYPHMETRICS metrics;
// identity matrix, required
MAT2 matrix = new MAT2
{
eM11 = {value = 1},
eM12 = {value = 0},
eM21 = {value = 0},
eM22 = {value = 1}
};
// HDC needed, we use a bitmap
using(Bitmap b = new Bitmap(1,1))
using (Graphics g = Graphics.FromImage(b))
{
IntPtr hdc = g.GetHdc();
IntPtr prev = SelectObject(hdc, font.ToHfont());
uint retVal = GetGlyphOutline(
/* handle to DC */ hdc,
/* the char/glyph */ letter,
/* format param */ GGO_METRICS,
/* glyph-metrics */ out metrics,
/* buffer, ignore */ 0,
/* buffer, ignore */ IntPtr.Zero,
/* trans-matrix */ ref matrix);
if(retVal == GDI_ERROR)
{
// something went wrong. Raise your own error here,
// or just silently ignore
return 0;
}
// return the height of the smallest rectangle containing the glyph
return metrics.gmBlackBoxY;
}
}
Can you update the question to include what you have tried ?
By dot glyph I assume you mean the punctuation mark detailed here ?
Is this Glyph height displayed on screen or a printed page ?
I managed to modify the first method in the link you posted in order to count the matching vertical pixels, however identifying the largest height of the glyph is fiddly to do unless you are willing to draw character by character, so this wasn't really a general working solution like the article.
In order to have a general working solution would need identify the largest single pixel vertical region of the character / glyph, then count the number of pixels in that region.
I also managed to verify that Graphics.MeasureString
, TextRenderer.MeasureText
and Graphics.MeasureCharacterRanges
all returned the bounding box which gave a number similar to the font height.
The alternative to this is to Glyph.ActualHeight
property which gets the rendered height of the framework element. This part of WPF and the related GlyphTypeface
and GlyphRun
classes. I wasn't able to test them at this time having only Mono.
The steps for getting Glyph.ActualHeight
are as follows
Initialise the arguments for GlyphRun
Initialise GlyphRun
object
Access relevant Glyph
using glyphTypeface.CharacterToGlyphMap[text[n]]
or more correctly glyphTypeface.GlyphIndices[n]
, where glyphTypeface
is your GlyphTypeface, which is created from the Typeface object you make in Step 1.
Relevant resources on using them include
Futher references on GDI (What these classes use under the hood is GDI or GDI+) and Fonts in Windows include
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With