Using Glyph objects | .NET
Working with glyphs is crucial when coding fonts as it is their unit. When the basic information about glyphs is explained in the article of the What is font paragraph, here we are going to teach you the functionality of Aspose.Font for working with glyphs and the Glyph objects in particular.
Glyph object
Glyphs of any font are represented by Glyph type in Aspose.Font library. So, Glyph type is a universal object for font glyphs, independently from font format(TrueType, Compact Font Format, etc).
The functionality provided by the Glyph object
What functionality does this object provide for us?
This question is answered by the properties it has.
- First, let’s look at the property State. Some of the fonts may be corrupted, and their glyphs also can be corrupted. Property State tells us whether the glyph is corrupted. If it has the value ParsedWithErrors, then that glyph was parsed with errors, and not all the glyph data was received.
- Properties WidthVectorX and LeftSidebearingX tell us about such glyph metrics as advance width and left side bearing correspondingly.
- Properties WidthVectorY and LeftSidebearingY have the same sense as WidthVectorX and LeftSidebearingX, but WidthVectorY and LeftSidebearingY are related to coordinates for the vertical Y-axis.
Let’s have an example with the next code snippet that sums glyph advances for the text “Hello world” at a font size of 10, without pair kerning. The result uses the same units as the font size; it is a pixel width if the size is specified in pixels.
Add the next namespaces at the head of the file:
1 using Aspose.Font;
2 using Aspose.Font.Glyphs;Before running the snippets, supply a loaded Aspose.Font.Font object named font. The tests load TTF/LatoWeb-Regular.ttf from DataDir, which points to tests-data/Aspose.Font in the examples project, using Font.Open with a FontDefinition, FontType.TTF, and a FileSystemStreamSource. In your application, use your own font data directory. This loading setup is outside the snippets.
The following example maps each Unicode character to its glyph with UnicodeToGid and sums the scaled advances. For the supplied Lato font, the result is 50.99:
1// Calculate text width from glyph advances
2
3const string text = "Hello world";
4const int fontSize = 10;
5double width = 0;
6
7// Sum glyph advances at the requested size, without pair kerning.
8foreach (char symbol in text)
9{
10 GlyphId gid = font.Encoding.UnicodeToGid(symbol);
11 Glyph glyph = font.GetGlyphById(gid);
12 width += ((double)glyph.WidthVectorX / font.Metrics.UnitsPerEM) * fontSize;
13}To get the glyph’s Bounding box use the GlyphBBox property of the Glyph object.
To get a visual representation of glyphs you need to know the coordinates for all glyphs’ points.
How to get coordinates for all glyph points from the Glyph object?
The next properties, IsEmpty and Path were designed for this case.
Property IsEmpty is auxiliary. It tells us whether the glyph’s path is empty, or in other words glyph has no drawing instructions at all. If it has the value false, it’s time to construct the whole glyph’s figure using the very useful property Path.
In the concept of Aspose.Font library the representation of any glyph is divided into the simplest graphic primitives, called segments, and represented by interface IPathSegment. Interface IPathSegment is a base abstract graphic primitive.
Concrete graphic primitives are represented by such types as MoveTo, LineTo, CurveTo, and ClosePath.
Type ClosePath is used to indicate the end of the current graphic contour.
Types MoveTo, LineTo, and CurveTo by their definition correspond with the identical postscript operators.
Also, the types MoveTo and LineTo by their definition correspond to the functions MoveToEx() and LineTo() from windows GDI lib, type CurveTo is used to describe Bézier curves.
Glyph property Path provides us with a collection of all graphic primitives for that glyph.
Property Path has type SegmentPath and every object of this type has property Segments of type PathSegmentCollection. This property Segments returns all the graphic primitives which object SegmentPath includes. In other words, we can get all the graphic primitives for the glyph using the entry glyph.Path.Segments.
The next
example collects path endpoints and Bézier control points in points, a list of objects of type
Point. The casts to int truncate fractional coordinates.
This sample does not group points into contours or process ClosePath. To reconstruct contours, track contour boundaries and handle ClosePath as well.
Add the next namespaces at the head of the file:
1 using System.Collections.Generic;
2 using Aspose.Font.Glyphs;
3 using Aspose.Font.RenderingPath;
4 using Point = System.Drawing.Point;Before running this snippet, obtain a nonempty Glyph named glyph from the loaded font, for example with font.GetGlyphById(font.Encoding.UnicodeToGid('S')). The tests use the glyphs for A and S. Glyph selection and validation are outside the snippet.
1// Collect integer coordinates from a glyph path
2
3List<Point> points = new List<Point>();
4IPathSegment? prevSegment = null;
5
6// Collect endpoints and Bezier control points without grouping contours.
7foreach (IPathSegment segment in glyph.Path.Segments)
8{
9 if (segment is LineTo || segment is CurveTo)
10 {
11 if (prevSegment is MoveTo moveTo)
12 {
13 AddPoint((int)moveTo.X, (int)moveTo.Y, points);
14 }
15 if (segment is LineTo line)
16 {
17 AddPoint((int)line.X, (int)line.Y, points);
18 }
19 else if (segment is CurveTo curve)
20 {
21 AddPoint((int)curve.X1, (int)curve.Y1, points);
22 AddPoint((int)curve.X2, (int)curve.Y2, points);
23 AddPoint((int)curve.X3, (int)curve.Y3, points);
24 }
25 }
26 prevSegment = segment;
27}
28
29void AddPoint(int x, int y, List<Point> target)
30{
31 target.Add(new Point(x, y));
32}How to calculate kerning value for glyphs?
Another Glyph metric but the one that is not supplied by the Glyph-type object. Here we are talking about kerning. Such a characteristic as kerning, applies not to one but to a pair of glyphs. So to calculate kerning you need to use the identifier not of one but of two glyphs.
Interface IFontMetrics in Aspose.Font library defines method GetKerningValue() which takes glyph identifiers for a glyphs pair and returns a kerning value, related to that pair. If no kerning information exists for glyphs pair, the method returns 0. Implementation of IFontMetrics interface exists for all classes of supported font formats and it is accessible using property Metrics.
Using the same loaded font, the next snippet gets the kerning value for the glyphs associated with A and C. For the supplied Lato font, this pair has no adjustment and the result is 0:
1// Get kerning for the glyphs associated with A and C
2
3double kerning = font.Metrics.GetKerningValue(
4 font.Encoding.UnicodeToGid('A'), font.Encoding.UnicodeToGid('C'));How To obtain glyphs from font?
Any glyph in a font can be accessed by a special glyph identifier. This rule is true for any font format.
Glyph identifiers GlyphId can be of two types: integer or string. These GlyphId data types are linked with such glyph characteristics as glyph index and glyph name correspondingly.
Also, each glyph has an index equal to its numbering in the font. An important moment is that the numbering starts not from 1 but from 0 so if a font contains of 15 glyphs, they have Glyph IDs 0–14.
The glyphs usually also have glyph names which are brief ASCII text labels without spaces. For example, the glyph name for symbol “+” is “plus”.
So the data type integer corresponds with such a characteristic of the glyph as glyph index, and the data type string corresponds with the name of the glyph.
Each glyph of a font represents the image of the symbol which this glyph is associated with so the glyph is linked not only to its identifier but to the unique code corresponding to this symbol.
The relation between character codes and glyph identifiers is called encoding. Glyphs in the font can be accessed directly by glyph identifiers or using encoding.
In the last case first, the glyph identifier based on the character code is calculated. Then the glyph corresponding to the calculated identifier is received.
What type of glyph identifier should be used to access the desired glyph?
It depends on the format of the font. Glyphs in fonts of Type 1 Font Format and Compact Font Format (CFF) are accessible by the glyph name. Actually, glyphs in fonts of these formats are kept as an array and are physically accessible via numerical index but on the higher logical level for getting a glyph its name is used.
TrueType fonts use integer type for glyph identifiers. If the TrueType font has ‘post’ table, glyph name or a glyph identifier of string type can be used to access the glyph.
Retrieving glyphs from font using Aspose.Font library.
Aspose.Font library introduces namespace Aspose.Font.Glyphs where glyphs, glyph identifiers, and other objects are placed. Class GlyphId is a base abstract class for glyph identifiers. Objects of that class are used to get desired glyphs.
Glyph identifiers for integers and a string type are represented by classes GlyphUInt32Id and GlyphStringId correspondingly.
Both these classes are inherited from the base abstract class GlyphId and particularly the objects of this abstract class GlyphId are passed in the function of the library for access to the needed glyph. So to get the required glyph you create a GlyphUInt32Id or GlyphStringId-type object and then pass the created object to one of the functions that are designed for retrieving glyphs.
In most cases, you do not know which glyph identifier corresponds to the specific character so to get the glyph identifier you need to find the relation between character code and glyph identifier.
As it was mentioned above, font encoding is responsible for such relations. Base font encoding functionality is defined by the IFontEncoding interface.
Base interface IFont implemented by all font classes defines property Encoding of type IFontEncoding, so any font object created by Aspose.Font library provides implementation for IFontEncoding functionality by the property Encoding.
Next methods were designed to calculate glyph identifier for a character code: UnicodeToGid(), DecodeToGid and DecodeToGidParameterized:
- Use method UnicodeToGid() if your character code is unicode.
- If your character code is not unicode use DecodeToGid() method.
- Method DecodeToGidParameterized() is designed for compound cases when special parameters are needed to calculate glyph identifiers.
After you get a glyph identifier or in other words a reference to the GlyphId object, you can get the glyph associated with this GlyphId using functionality, defined by the interface IGlyphAccessor.
The interface IGlyphAccessor is implemented by any class, derived from the base Font class and it’s accessible by the IFont.GlyphAccessor property.
Interface IGlyphAccessor defines the method GetGlyphById(). Use this method to get the glyph for GlyphId passed.
The example of how to use the GetGlyphById method to get GlyphId and the corresponding glyph is included in the example from the The functionality provided by the Glyph object chapter.
The next 2 methods of this interface are designed to get glyph identifiers:
- If you need to get a glyph identifier for every character in some text string, you can use the method GetGlyphsForText().
- Method GetAllGlyphIds() is designed to get all glyph identifiers, available in the font.
Also, interface IGlyphAccessor defines the property GlyphIdType which tells us what data type, integer, or string имеет glyph identifier.
Support for retrieving glyphs is more powerful for TrueType fonts. Here you can find the information on how to get access to font glyphs.
All the examples of using the Aspose.Font are stored in Aspose.Font.Examples.sln solution, in the net-examples of the Aspose.Font Documentation
If you have any issues, you may post them at the Aspose.Font.Product Family section of the Free Support Forum and within a few hours our support team will clear everything up for you.