In order to support this under win32, you should extract the GSUB table of an opentype font (see here: http://www.microsoft.com/Typography/OTSpec/otff.htm ).
This table is used to look backward in the entered text and perform glyph substitution. For example, in French for coeur, when you type “coe”, the GSUB table states that o followed by e should be replaced by glyph “œ” to form the true word “cœur”.
In linux, it’s exactly the same, as FreeType2 gives access to such table.
Please notice that, in French it’s probably ok not to do ligature, in Hindi or Arabic, it make any text unreadable.
In Juce, last time I’ve checked this, it doesn’t read such table, and, of course doesn’t check such substituation table while rendering the glyphs.
Notice that it requires a lot of brain space to implement, it’s not easy, so it’s unlikely it’ll be done soon.
Yes, he is right. I am also interested to know about the unicode. Because my friend is using mac os while i am using Linux os. There is unicode problem. Any hint for this. I could not got the solution yet.
Not to forget the issue, I’ve done some searching on the ligature tab parsing in TTF and OTF files, and this is what I’ve found so far, it’s a GSUB table parser, but specifically it’s the ligature parser.
I think the other substitution are not as important as the ligatures, so they can probably be ommitted.
By going other the Juce code base, I think ligature substitution can be added transparently in the GlyphArrangement code. Let me know if you think it’s correct.
The basic algorithm is explained here http://www.microsoft.com/Typography/OTSpec/gsub.htm#EX6
// Code from adobe's Tin opensource package, not specialized to GSUB at all, but easy to follow
// http://opensource.adobe.com/svn/opensource/tin/src
// Comments are my own, the source code doesn't have any
// Typically, on a GSUB table, we are only looking for the table with type 4: Ligature
// image is a file object, Read2() reads BigEndian 16bits, other methods are obvious
LookupType * Read4 (FileImage::Reader &image, FontUtilsConstPtr utils)
{
Format4 * lookup = new Format4;
size_t posTableOffset = image.Position();
uint16_t format = image.Read2();
if (format != 1)
throw Error (format2UnknownSubstitutionFormat);
// GID are Glyph's ID as saved in the font's index
OrderedGIDs gids;
size_t coverageOffset = posTableOffset + static_cast <size_t> (image.Read2());
size_t ligSetCount = static_cast <size_t> (image.Read2());
{
// I think this save the file's position and restore on destructor
FileImage::State state (image);
image.Seek (coverageOffset);
// The coverage table says how many & which glyphs are concerned by the ligature substitution
(void) ReadCoverage (image, gids);
if (gids.size() != ligSetCount)
throw GSUBLookup::Error (coverageMismatch);
}
for (size_t six = 0; six != ligSetCount; ++six)
{
LigatureSet * ligSetPtr = new LigatureSet;
LigatureSet & ligSet (*ligSetPtr);
size_t ligSetOffset = posTableOffset + static_cast <size_t> (image.Read2());
FileImage::State state (image);
image.Seek (ligSetOffset);
size_t ligCount = static_cast <size_t> (image.Read2());
ligSet.resize (ligCount);
for (size_t lix = 0; lix != ligCount; ++lix)
{
LigatureTable & ligTable (ligSet [lix]);
size_t ligOffset = ligSetOffset + static_cast <size_t> (image.Read2());
FileImage::State state (image);
image.Seek (ligOffset);
GlyphTag ligGlyph = utils->GlyphTagFromGlyphIDNoCheck (image.Read2());
size_t compCount = static_cast <size_t> (image.Read2());
// The glyph to replace by
ligTable.reserve (compCount);
ligTable.push_back (ligGlyph);
// The number of components that cause the replacement
for (size_t cix = 1; cix < compCount; ++cix)
ligTable.push_back (utils->GlyphTagFromGlyphIDNoCheck (image.Read2()));
}
GlyphTag tag = utils->GlyphTagFromGlyphIDNoCheck (gids [six]);
// This basically says that the glyph "Tag" have a table of substitution attached.
lookup->ligatures.map [tag] = LigatureSetPtr (ligSetPtr);
}
return lookup;
}