Problem of Thai marks (tone marks)

Yes, you definitely need a calt feature. As it’s not compiling by itself (I don’t know why not, hopefully someone else can answer that), you could try writing the feature yourself. Here’s a runthrough of what you’ll need:

 ## First define your classes (check the glyph names accord with what you have in your font):

@topvowels = [saraI-thai saraIi-thai saraEu-thai saraEuu-thai maiHanakat-thai];
@tonemarksdefault = [maiEk-thai maiTho-thai maiTri-thai maiCattawa-thai thanthakhat-thai];
@tonemarksupstairs = [maiEk-thai.calt maiTho-thai.calt maiTri-thai.calt maiCattawa-thai.calt thanthakhat-thai.calt];

 ## Then switch @tonemarksdefault to @tonemarksupstairs following any of the @topvowels:

sub @topvowels @tonemarksdefault' by @tonemarksupstairs;

 ## Note tonemarks are typed before SaraAm so the order is different:

sub @tonemarksdefault' thSaraAm by @tonemarksupstairs;
1 Like

You cannot autogenerate calt because Glyphs cannot guess what you intend as context. Contextual alternates should not have the automate option in the first place, I guess.

I wonder if the feature code should not better go into ccmp.

2 Likes

Why’s that?

You can’t disable it and it’s always on.

I see. I wondered if you meant Glyphs could compile the feature itself that way. There’s also an rclt feature, which might also be unswitchoffable.

1 Like

If this is supposed to be in every Thai font, we can add it to the feature generator.

Is it supported well enough? Have you tried?

like @mekkablue mentioned, this is what I’ve already implemented in the ccmp feature:

still not working.
I tend to believe the simple positioning in compound glyphs, that Unicode is offering, is most likely to always work as fall back: ก + ◌ี + ◌้ → กิ้ (just noticed that the 2nd level here is working, for what ever reason). Although native readers experience this as readable but not looking good.

I haven’t tried rclt, nor ccmp for this sort of thing; I’ve always put these contextual substitutions in the calt feature, which has worked universally in my tests. (It’s also handy for testing, to be able to switch off contextual alternates in InDesign, to make sure the feature is doing what it’s supposed to.)

Yes, by all means. add this to the feature generator. I thought it was there already, hence my confusion :slight_smile:

Here’s the full features for Thai (except for contextual kerning, which can’t be auto-generated):

##classes

@thaiAboveMarks = [nikhahit-thai maiChattawa-thai maiEk-thai maiHanaKat-thai thanthakhat-thai maiTho-thai maiTri-thai maitaikhu-thai yamakkan-thai saraI-thai saraIi-thai saraUe-thai saraUee-thai];
@thaiBelowMarks = [saraU-thai saraUu-thai phinthu-thai];
@thaiBelowMarksSmall = [saraU-thai.small saraUu-thai.small phinthu-thai.low];
@thaiToneMarks = [maiEk-thai maiTho-thai maiTri-thai maiChattawa-thai thanthakhat-thai];
@thaiToneMarksUp = [maiEk-thai.small maiTho-thai.small maiTri-thai.small maiChattawa-thai.small thanthakhat-thai.small];

##ccmp

lookup thaiDecompose {
	sub saraAm-thai by nikhahit-thai saraAa-thai;
} thaiDecompose;

##calt

lookup thaiCalt { 
		# if shortened consonants are in the font, use these when vowels are present:
		sub [doChada-thai toPatak-thai]' @thaiBelowMarks by [doChada-thai.short toPatak-thai.short];
		# if small vowels are in the font, also use these on the shortened consonants:
		sub [doChada-thai.short toPatak-thai.short] @thaiBelowMarks' by @thaiBelowMarksSmall;
		# Use tail-less versions of consonants when belowmarks are present:
		sub [yoYing-thai thoThan-thai]' @thaiBelowMarks by [yoYing-thai.less thoThan-thai.less];
		sub loChula-thai' @thaiBelowMarks @thaiAboveMarks by loChula-thai.short;
		sub loChula-thai' @thaiAboveMarks by loChula-thai.short;
		} thaiCalt;

lookup thaiUpstairsToneMarks { 
		# replaces tonemarks with smaller upstairs versions when another abovemark vowel intervenes:
		sub @thaiAboveMarks @thaiToneMarks' by @thaiToneMarksUp;
		# If ligatures involving @thaiAboveMarks are present in the font, use @thaiToneMarksUp on these:
		sub @thaiAboveMarks [poPla_maiHanakat-thai foFa_maiHanakat-thai foFan_maiHanakat-thai poPla_nikhahit-thai poPla_saraI-thai poPla_saraIi-thai poPla_saraUe-thai poPla_saraUee-thai foFa_nikhahit-thai foFa_saraI-thai foFa_saraIi-thai foFa_saraUe-thai foFa_saraUee-thai foFan_nikhahit-thai foFan_saraI-thai foFan_saraIi-thai foFan_saraUe-thai foFan_saraUee-thai] @thaiToneMarks' by @thaiToneMarksUp;
		} thaiUpstairsToneMarks;

##liga

lookup thaiLigatures { # Ligate lu and ru to make luu and ruu;
		sub lu-thai lakkhangyao-thai by lu_lakkhangyao-thai;
		sub ru-thai lakkhangyao-thai by ru_lakkhangyao-thai;
		} thaiLigatures;

Note Unicode encodes characters, not glyphs, which is why no alternate versions are encoded.

2 Likes

fortunately was being generated automatically in liga:

i recon phinthu-thai.low is phinthu-thai.small when you’re adding missing letter (ctrl+click on Thai in Languages) in glyphs.

That’s good.

Yes. I think I called my alternate version .low rather than .small as the size was the same, but it just had different anchors or position. .small is probably a better general solution.

1 Like

(For reference, although all these .short, .small or .low glyphs show as ‘missing’ glyphs in the Languages list, the list is not meant to dictate what glyphs are necessary, only that they’re possible to include. They’re all optional, and depend on your own judgment and what suits the design.)

2 Likes

Most of the features should be auto generated and it will put it into ccmp and liga.

1 Like

In which app are you testing?

@GeorgSeifert Does Glyphs write the Languagesystem feature by itself too? And what was your final decision about writing the lookups twice, once for dflt and once for thai script?

adobe photoshop and indesign, microsoft excel and word.

I can’t get these scripts going. Is there a chance that you might have a look at my .glyphs -file?

Sure, I can take a look. Send to ben [at] fontpad [dot] co [dot] uk

1 Like

Ok I’ve received your Glyphs file. I thought it best to write here so others can benefit if they’re having similar problems.

First of all, I’d put the glyphs in a logical order so we can see what we have. Currently different glyph alternates are not adjacent, and things of different kinds are scrambled together. With the glyphs you have, I’d put them in this order:

zero-thai
one-thai
two-thai
three-thai
four-thai
five-thai
six-thai
seven-thai
eight-thai
nine-thai
koKai-thai
khoKhai-thai
khoKhuat-thai
khoKhwai-thai
khoKhon-thai
khoRakhang-thai
ngoNgu-thai
choChan-thai
choChing-thai
choChang-thai
soSo-thai
choChoe-thai
yoYing-thai
yoYing-thai.less
doChada-thai
doChada-thai.short
toPatak-thai
toPatak-thai.short
thoThan-thai
thoThan-thai.less
thoNangmontho-thai
thoPhuthao-thai
noNen-thai
doDek-thai
toTao-thai
thoThung-thai
thoThahan-thai
thoThong-thai
noNu-thai
boBaimai-thai
poPla-thai
phoPhung-thai
foFa-thai
phoPhan-thai
foFan-thai
phoSamphao-thai
moMa-thai
yoYak-thai
roRua-thai
loLing-thai
woWaen-thai
soSala-thai
soRusi-thai
soSua-thai
hoHip-thai
loChula-thai
loChula-thai.short
oAng-thai
hoNokhuk-thai
ru-thai
lu-thai
ru_lakkhangyao-thai
lu_lakkhangyao-thai
saraAa-thai
saraAm-thai
lakkhangyao-thai
saraA-thai
saraE-thai
saraAe-thai
saraO-thai
saraAiMaimuan-thai
saraAiMaimalai-thai
maiHanaKat-thai
maiHanaKat-thai.narrow
saraI-thai
saraI-thai.narrow
saraIi-thai
saraIi-thai.narrow
saraUe-thai
saraUe-thai.narrow
saraUee-thai
saraUee-thai.narrow
saraU-thai
saraU-thai.small
saraUu-thai
saraUu-thai.small
phinthu-thai
phinthu-thai.small
maitaikhu-thai
maitaikhu-thai.small
maitaikhu-thai.narrow
yamakkan-thai
maiEk-thai
maiEk-thai.small
maiEk-thai.narrow
maiTho-thai
maiTho-thai.small
maiTho-thai.narrow
maiTri-thai
maiTri-thai.small
maiTri-thai.narrow
maiChattawa-thai
maiChattawa-thai.small
maiChattawa-thai.narrow
thanthakhat-thai
thanthakhat-thai.small
thanthakhat-thai.narrow
nikhahit-thai
nikhahit-thai.narrow
nikhahit_maiEk-thai
nikhahit_maiEk-thai.narrow
nikhahit_maiTho-thai
nikhahit_maiTho-thai.narrow
nikhahit_maiTri-thai
nikhahit_maiTri-thai.narrow
nikhahit_maiChattawa-thai
nikhahit_maiChattawa-thai.narrow
baht
angkhankhu-thai
fongman-thai
khomut-thai
maiyamok-thai
paiyannoi-thai

Once that’s done, I can see three glyphs which are redundant:
ru-thai.short
lu-thai.short
loChula-thai.less

The first two of those were mistakenly introduced to Glyphs a while ago, but they’re vowel letters so will never need short versions as they don’t take any marks ever. I’ve no idea why you have the third of these, as you already have loChula-thai.short. Note also doChada-thai.short and toPatak-thai.short should be different to doChada-thai and toPatak-thai: their descenders should be shorter to accommodate below marks. Similarly, SaraU-thai and SaraUu-thai should have .small versions that are actually smaller than the default versions, otherwise there’s no reason to include alternate glyphs. Also note your upstairs tone marks should be drawn smaller than the default forms (they’re operating on the vowel marks, which are quite a lot smaller than the consonants).

Next I notice you have Thai glyphs called glyph99, glyph100, glyph101, and then uniF701, uniF702 etc that I can see no purpose for. You do not need to use the Private Use Area for Thai. Delete all these glyphs (if you need to store alternate versions of outlines, use different Layers within a glyph, not new glyphs).

Next I’d clean up the features by splitting different kinds of operations into different lookups. I’d also put glyphs into classes so it’s cleaner and easier to see what’s happening in the lookups. While looking at features, I also notice you have the script thai; tag in all the lookups; this will mean the OT features will only work when the user declares the text’s language as Thai.

I notice is you have not only default and .small versions of marks, but also .narrow versions of most marks too. I personally never use .narrow versions, but as you have them, they should be substituted in above a consonant with an ascending stem, as these have less horizontal space above. I see you have some of these written in your lookup, but three of the .narrow glyphs are missing (maiEk-thai.narrow maiChattawa-thai.narrow nikhahit-thai.narrow), so either add them or remove the glyphs if they’re not going to be used.

With that taken care of, you now need to fix what happens when tone marks appear on these narrow marks, so we’ll need to include the .narrow versions in the lookup that calls the upstairs tone marks.

We also have quite a number of glyphs that are ligatures of marks. I’ve never found these necessary, since we use mark-to-mark positioning. So I’m not sure why you have glyphs like nikhahit_maiEk-thai.small and nikhahit_maiEk-thai.narrow.

Finally, I notice most of your consonants do not have anchors. Every consonant should have a top anchor and a bottom anchor. Put bottom anchors at the base of the right hand stem at y=0, and top anchors at a consistent height e.g. y=500, again above the right hand stem, where you want the marks to align. Then, make sure that any abovemarks have _top anchors (at the same height you chose for the top anchors on the consonants) and top anchors higher up, for the upstairs tone marks to attach to (e.g. at y=650). Then the upstairs tone marks just need _top anchors at y=650. Belowmarks should just have _bottom anchors at y=0.

I’ll send the file back with the OT stuff fixed, and anchors in good positions for koKai-thai, saraI-thai and maiEk-thai so you can see the pattern to use for all the other marks.

2 Likes

@GeorgSeifert One of the problems we had here was that the Subcategory for all the Thai consonants was ‘other’. As I’ve said repeatedly about several different scripts, the mark and mkmk features only compile when all marks are set to ‘mark + nonspacing’ and all bases are set to ‘letter + spacing’. No other combination of category/subcategory builds those features which means exported fonts do not work. As Glyphs is meant to do the automatic stuff even for beginners, shouldn’t it be correct? I’m sorry for my frustration but it feels like I’ve been pointing this out for years.