[Question] about unicode


#1

hello there,
quite a brilliant tookit yout got there , but i wonder if it suppoer unicode, RTL language like arabic

i searched for a good tks and didnt like most ( in fact all ) of the popular ones out there, started in some QT stuff but didnt go through anymore

i like the look and feel of JUCE and i want to make some public open source cross-platform applications ( for instance a gtalk client :slight_smile: )

regards,
AAly


#2

It doesn’t support font ligature required in arabic’s (and hindi, and thai, etc…) font rendering.


#3

I think it might support that now on the mac… can’t remember exactly what the status of it was. Not on win32 or linux though.


#4

was looking forward to the arabic fonts support :frowning:

i mainly develop for linux and windows :slight_smile:

thanks.


#5

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.


#6

Yes, it’s not my top priority right now, I’m afraid. I’d certainly like to implement it when I get chance though!


#7

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.


#8

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;
	}