Developing and generating Arabic fonts is not as easy and straightforward as for Latin fonts.This article will cover Encoding, Glyph and Font naming, OpenType features and other topics concerning the preparation of an Arabic font before generating it.

generating-arabic-fonts.png


When I was working on my graduation Arabic type family Massira at kabk I was asking all sorts of questions about the proper way of generating my Arabic fonts, but I was not able to get any clear answers or sometimes no answers at all. Experience from Arabic type design projects, research about Arabic fonts, sharing information with type design colleague and writing on the ATypI mailing list enabled me to gather all this information. I decided to write an article about all the technical requirements regarding Arabic fonts and make it available to all young Arabic type designers once and for all. I hope that this kind of sharing spirit to become present in all the Arabic type design community and make information available to everyone and not keep it hidden.

—————————————————————————————
—————————————————————————————
—————————————————————————————
—————————————————————————————

1. Encoding & Arabic Glyph Naming:

Upon starting to digitize an Arabic font, an Arabic type designer needs to create his/her own encoding for the font. Unicode presents four Character Code Charts for the Arabic Script, but none of the four can be used separately. That is why each Arabic type designer needs to create his/her own encoding depending on the use of the font and the languages it needs to support beside basic Arabic (like Persian, Urdu…). The four encoding charts are:

1. ‘Arabic’ contains only the isolated letterforms of the basic and extended Arabic.

2. ‘Arabic Supplement’ contains the extended Arabic letters needed for African languages that uses the Arabic script.

3.’ Arabic Presentation Forms A’ contains the extended Arabic letters and all the Arabic ligatures or mergers.

4. ‘Arabic Presentation Forms B’ contains all the basic Arabic character set in isolated, initial, medial and final forms.

An Arabic font that only needs to support the Arabic language; ‘Arabic’ and ‘Arabic Presentation Form B’ are needed. If the font needs to support other Asian languages that use the Arabic script (like Persian and Urdu); ‘Arabic’, ‘Arabic Presentation Form A’ and ‘Arabic Presentation Form B’ are needed. If a font is developed for the African languages that uses the Arabic script; ‘Arabic’, ‘Arabic supplement and ‘Arabic Presentation Form B’ are needed. And so forth.

In Fontlab only one of the four encoding can be selected at one time. It can be frustrating to depend only on the Unicode Code Charts found within Fontlab during the design process of an Arabic type. Below is part of one of my own encoding for a basic Arabic font:

—————————————————————————————
%%FONTLAB ENCODING: 234574; Pascal-Arabic-Basic

hamza.isol
alef.isol
alef.fina
alef_madda.isol
alef_madda.fina
alef_hamza_above.isol
alef_hamza_above.fina
alef_hamza_below.isol
alef_hamza_below.fina
beh.isol
beh.init
beh.medi
beh.fina
peh.isol
peh.init
peh.medi
peh.fina
teh.isol
teh.init
teh.medi
teh.fina
tehmarbuta.isol
tehmarbuta.fina
theh.isol
theh.init
theh.medi
theh.fina
jeem.isol
jeem.init
jeem.medi
jeem.fina
hah.isol
hah.init
hah.medi
hah.fina
khah.isol
khah.init
khah.medi
khah.fina
dal.isol
dal.fina
thal.isol
thal.fina
reh.isol
reh.fina
zain.isol
zain.fina
seen.isol
seen.init
seen.medi
seen.fina
[…]
—————————————————————————————

Encoding files are not that hard to write. All files need to start with this (%%FONTLAB ENCODING: 234574; Pascal-Arabic-Basic). After the colon you need the change the number and give a different number to each encoding file, and then give it a name after the semicolon like in the example. The files needs to be saved as “xxxx.enc” file and placed in the “Encoding folder inside Fontlab in the application folder. When you add your own encoding you will notice that now it will appear in the encoding list inside Fontlab and you can use it to develop your Arabic font.

After writing your own encoding file with your own glyph naming, a ‘Mapping’ file needs to be written and added to the “agl.nam” and the “STANDARD.nam” mapping files that are found in Fontlab. Mapping files are needed by Fontlab to find the right unicode for each glyph name. Below is part of the mapping script needed for my own encoding:

—————————————————————————————
% Pascal defined Basic Arabic & Persion & Urdu
0×0621 hamza.isol
0xFE80 hamza.isol
0×0627 alef.isol
0xFE8D alef.isol
0xFE8E alef.fina
0×0622 alef_madda.isol
0xFE81 alef_madda.isol
0xFE82 alef_madda.fina
0×0623 alef_hamza_above.isol
0xFE83 alef_hamza_above.isol
0xFE84 alef_hamza_above.fina
0×0625 alef_hamza_below.isol
0xFE87 alef_hamza_below.isol
0xFE88 alef_hamza_below.fina
0×0671 alef_wasla.isol
0xFB50 alef_wasla.isol
0xFB51 alef_wasla.final
0×0628 beh.isol
0xFE8F beh.isol
0xFE91 beh.init
0xFE92 beh.medi
0xFE90 beh.fina

%persian Character
0x067E peh.isol
0xFB56 peh.isol
0xFB58 peh.init
0xFB59 peh.medi
0xFB57 peh.fina

%urdu characters
0×0679 tteh.isol
0xFB66 tteh.isol
0xFB68 tteh.init
0xFB69 tteh.medi
0xFB67 tteh.fina
0x06C3 tehmarbuta_goal.isol
tehmarbuta_goal.fina

[…]
—————————————————————————————

Since the isolated Arabic glyphs are found in the “Arabic” and “Arabic Presentation Forms B” Code Charts, you notice that the names of all the isolated glyphs are repeated twice with different unicodes. All Isolated Arabic letter have double unicodes and they need to be both present in the font. Initial, medial and final glyphs are only written once since they are only present in “Arabic Presentation Forms B” Code Chart and have only one unicode each.

Moving on to the Arabic glyph naming, you can notice that the names in my list are different from the ones found in the Unicode Arabic Character Code Charts. The names given by Unicode are so long and somehow complex. In Fontlab, Arabic glyph do not have letter names as for the Latin letters but have instead “afiixxxx” or “unixxxx” names which is not at all friendly for an Arabic type designer whilst still in the design process of the font and needs to place, draw and modify his/her Arabic glyphs.

Developing Fonts that work with Quark Arabic AXt is another story. AXt Arabic font use the ‘Mac Roman’ encoding and the Arabic glyphs are placed in place of the Roman glyphs. Open an AXt font in Fontlab or Fontrographer and notice where the Arabic letters are places. Below is part of the list of replacements:

The list is written in the following method:
“Roman Glyph” / “Arabic glyph that is placed instead”,
—————————————————————————————
[…]
“G” / “alef.isol”,
“H” / “beh.init”,
“I” / “tehmarbuta.isol”,
“J” / “teh.init”,
“K” / “theh.init”,
“L” / “jeem.init”,
“M” / “hah.init”,
“N” / “khah.init”,
“O” / “dal.isol”,
“P” / “thal.isol”,
“Q” / “reh.isol”,
“R” / “zain.isol”,
“S” / “seen_alt.init”,
“T” / “sheen_alt.init”,
“U” / “sad_alt.init”,
“V” / “dad_alt.init”,
“W” / “tah.init”,
“X” / “zah.init”,
“Y” / “ain.init”,
“Z” / “ghain.init”,
“a” / “feh.init”,
“b” / “qaf.init”,
“c” / “kaf.init”,
“d” / “lam.init”,
“e” / “meem.init”,
“f” / “noon.init”,
[…]
—————————————————————————————

p.s.:This list is for QuarkAXt on Mac. If the font needs to work also on QuarkAXt on PC Windows, then two glyphs need to be switched: ’97′ with ’7E’ & ‘A0′ with ‘CA’ in the Hexa decimal encoding. So the font needs to be generated twice once for Mac and once for PC Windows.

For AXt Arabic fonts, beside changing the encoding of the Arabic letters, the ‘seen’ and ‘sad’ glyphs need to be modified. In the AXt encoding there is no place for the final and isolated shapes of the ‘seen’ and the ‘sad’, instead one medial stroke and one ending stroke are drawn that will be positioned after the initial and medial shapes of the ‘seen’ and the ‘sad’ in order to create ‘seen.fina, ‘seen.isol’, ‘sad.fina’ and ‘sad.isol’. Open an Axt Arabic font and notice this point.

If an Arabic font already exists and is not done primarily for QuarkAXt users, then it is wise to write a Python script (name.py) and use Robofab to create a new font and replace your Arabic glyphs into the Latin glyphs as in the list above. (The python script needs to by placed in the ‘Macros’ folder in Fontlab).

Below is part of an example of a python script. This script was written by my colleague type designer Frederik Frelaen.
—————————————————————————————
arabicToLatin = {

[…]
“G” : “alef.isol”,
“H” : “beh.init”,
“I” : “tehmarbuta.isol”,
“J” : “teh.init”,
“K” : “theh.init”,
“L” : “jeem.init”,
“M” : “hah.init”,
“N” : “khah.init”,
“O” : “dal.isol”,
“P” : “thal.isol”,
“Q” : “reh.isol”,
“R” : “zain.isol”,
“S” : “seen_alt.init”,
“T” : “sheen_alt.init”,
“U” : “sad_alt.init”,
“V” : “dad_alt.init”,
“W” : “tah.init”,
“X” : “zah.init”,
“Y” : “ain.init”,
“Z” : “ghain.init”,
[…]
}
def dictReverse(d):
new = {}
for key, item in d.items():
new[item] = key
return new
latinToArabic = dictReverse(arabicToLatin)

from robofab.world import CurrentFont, NewFont
import os

f = CurrentFont()

newF = NewFont()

### choose the path of the encoding you want

encoding= ‘/Library/Application Support/FontLab/Encoding/T1 Roman-Western/mac_roman.enc’

newF.naked().encoding.Load(encoding)

print “placing glyphs…”

for latinName, arabicName in arabicToLatin.items():
if f.has_key(arabicName):
print “/tplace”, arabicName, “in”, latinName

glyphToPlace = f[arabicName].copy()
glyphToPlace.decompose()
newG = newF.insertGlyph(glyphToPlace, as=latinName)
newG.unicodes = []
newG.autoUnicodes()
newG.update()
else:

print “\t>>>>>> glyph:”, arabicName, “is not available”

print “placing done”

####
print “autonaming…”
## autoNaming
newF.info.autoNaming(f.info.familyName, f.info.styleName)
print “autonaming done”

## import and replace names for kerning
print “kerning…”
kerning = f.kerning

newKern = newF.kerning

newKernDict = {}
for (left, right), value in kerning.items():
if latinToArabic.has_key(left) and latinToArabic.has_key(right):
newKernDict[(latinToArabic[left], latinToArabic[right])] = value

newKern.update(newKernDict)
print “kerning done”

newF.update()

—————————————————————————————
—————————————————————————————
—————————————————————————————
—————————————————————————————

2. Arabic OpenType Features:

Arabic OpenType font relies on Glyph names and OpenType features.
Below is a list of links that can be handy while starting to write Arabic OT features:
(Both Microsoft and Adobe websites have documentation on Arabic OT features.)
——————————————————————————————–

http://www.microsoft.com/typography/otfntdev/arabicot/features.htm

http://www.microsoft.com/typography/otspec/scripttags.htm

http://partners.adobe.com/public/developer/opentype/index_table_formats2.html

—————————————————————————————
—————————————————————————————

Brief steps for working with OT features will be:

A. Define the Classes.
—————————-
@_isolate= [alef.isol beh.isol];
@_initial= [alef.init beh.init];

B. Define the OT features that are going to be used.
——————————————————————-
feature aalt{ # All OT Features
feature init;
} aalt;

C. Use each feature to substitute or position glyphs.
—————————————————–
feature init { # initial Glyphs
script arab; # Arabic
lookupflag IgnoreMarks, RightToLeft;
sub @_isolate by @_initial;
} init;

Below is a basic Arabic OT feature file:
(Notice the classes are at the beginning of the file, then the defined OT features are written and finally each OT feature is used by itself)
—————————————————————————————
@_isolate= [alef.isol alef_madda.isol alef_hamza_above.isol alef_hamza_below.isol beh.isol peh.isol teh.isol tehmarbuta.isol theh.isol tcheh.isol jeem.isol hah.isol khah.isol dal.isol thal.isol reh.isol zain.isol jeh.isol seen.isol sheen.isol sad.isol dad.isol tah.isol zah.isol ain.isol ghain.isol feh.isol veh.isol qaf.isol kaf.isol kheh.isol Gaf.isol lam.isol meem.isol ghunna.isol noon.isol heh.isol waw.isol waw_hamza.isol alefmaksura.isol yeh.isol yeh_farisi.isol yeh_hamza_above.isol lam_alef.isol lam_alef_madda.isol lam_alef_hamza_above.isol lam_alef_hamza_below.isol];

@_initial = [alef.isol alef_madda.isol alef_hamza_above.isol alef_hamza_below.isol beh.init peh.init teh.init tehmarbuta.isol theh.init tcheh.init jeem.init hah.init khah.init dal.isol thal.isol reh.isol zain.isol jeh.isol seen.init sheen.init sad.init dad.init tah.init zah.init ain.init ghain.init feh.init veh.init qaf.init kaf.init kheh.init Gaf.init lam.init meem.init ghunna.isol noon.init heh.init waw.isol waw_hamza.isol alefmaksura.init yeh.init yeh_farisi.init yeh_hamza_above.init lam_alef.isol lam_alef_madda.isol lam_alef_hamza_above.isol lam_alef_hamza_below.isol];

@_medial = [alef.fina alef_madda.fina alef_hamza_above.fina alef_hamza_below.fina beh.medi peh.medi teh.medi tehmarbuta.fina theh.medi tcheh.medi jeem.medi hah.medi khah.medi dal.fina thal.fina reh.fina zain.fina jeh.fina seen.medi sheen.medi sad.medi dad.medi tah.medi zah.medi ain.medi ghain.medi feh.medi veh.medi qaf.medi kaf.medi kheh.medi Gaf.medi lam.medi meem.medi ghunna.fina noon.medi heh.medi waw.fina waw_hamza.fina alefmaksura.medi yeh.medi yeh_farisi.medi yeh_hamza_above.medi lam_alef.fina lam_alef_madda.fina lam_alef_hamza_above.fina lam_alef_hamza_below.fina];

@_final = [alef.fina alef_madda.fina alef_hamza_above.fina alef_hamza_below.fina beh.fina peh.fina teh.fina tehmarbuta.fina theh.fina tcheh.fina jeem.fina hah.fina khah.fina dal.fina thal.fina reh.fina zain.fina jeh.fina seen.fina sheen.fina sad.fina dad.fina tah.fina zah.fina ain.fina ghain.fina feh.fina veh.fina qaf.fina kaf.fina kheh.fina Gaf.fina lam.fina meem.fina ghunna.fina noon.fina heh.fina waw.fina waw_hamza.fina alefmaksura.fina yeh.fina yeh_farisi.fina yeh_hamza_above.fina lam_alef.fina lam_alef_madda.fina lam_alef_hamza_above.fina lam_alef_hamza_below.fina];

feature aalt{ # All OT Features
feature init;
feature fina;
feature medi;
feature rlig;
feature ccmp;
feature mkmk;
} aalt;

feature init { # initial Glyphs
script arab; # Arabic
lookupflag IgnoreMarks, RightToLeft;
sub @_isolate by @_initial;
language FRS ; # Farsi
} init;

feature medi { # Medial Glyphs
script arab; # Arabic
lookupflag IgnoreMarks, RightToLeft;
sub @_isolate by @_medial;
} medi;

feature fina { # Final Glyphs
script arab; # Arabic
lookupflag IgnoreMarks, RightToLeft;
sub @_isolate by @_final;
} fina;

feature ccmp { # Composed/Decomposed Glyphs
script arab; # Arabic
lookupflag IgnoreMarks, RightToLeft;
sub alef.isol hamza_above by alef_hamza_above.isol;
sub alef.isol hamza_below by alef_hamza_below.isol;
sub alef.isol madda by alef_madda.isol;
sub alef.fina hamza_above by alef_hamza_above.fina;
sub alef.fina hamza_below by alef_hamza_below.fina;
sub alef.fina madda by alef_madda.fina;
} ccmp;

feature rlig { # Required Ligatures
script arab; # Arabic
lookupflag IgnoreMarks, RightToLeft;
sub lam.isol alef.isol by lam_alef.isol;
sub lam.isol alef_hamza_above.isol by lam_alef_hamza_above.isol;
sub lam.isol alef_hamza_below.isol by lam_alef_hamza_below.isol;
sub lam.isol alef_madda.isol by lam_alef_madda.isol;
sub lam.fina alef.isol by lam_alef.fina;
sub lam.fina alef_hamza_above.isol by lam_alef_hamza_above.fina;
sub lam.fina alef_hamza_below.isol by lam_alef_hamza_below.fina;
sub lam.fina alef_madda.isol by lam_alef_madda.fina;
} rlig;

feature mkmk { # Mark to Mark
script arab; # Arabic
lookupflag IgnoreMarks, RightToLeft;
sub shadda dammatan by shadda_dammatan;
sub shadda damma by shadda_damma;
sub shadda fathatan by shadda_fathatan;
sub shadda fatha by shadda_fatha;
sub shadda kasratan by shadda_kasratan;
sub shadda kasra by shadda_kasra;
sub hamza_above dammatan by hamza_above_dammatan;
sub hamza_above damma by hamza_above_damma;
sub hamza_above fathatan by hamza_above_fathatan;
sub hamza_above fatha by hamza_above_fatha;
sub hamza_above sukun by hamza_above_sukun;
sub hamza_below kasra by hamza_below_kasra;
} mkmk;
—————————————————————————————
—————————————————————————————

Developing a perfectly working OT Arabic font requires the use of Fontlab and VOLT. Basic Arabic shaping (init, medi, fina, rlig, liga features)can be done by using only FontLab’s OTL support, where as VOLT is needed to do: 1/ dynamic mark positioning (mark feature & mkmk feature) for vowels or other marks and 2/ the cursive (curs feature) slanted vertical increments. Refer to the links to comprehend the difference between [GSUB = glyph substitution and [GPOS = glyph positioning].

So the question of whether to use FontLab or VOLT for developing OTL table depends on how sophisticated the Arabic font needs to be. If the Arabic font is only needed to work with Adobe ME applications and does not need to have dynamic mark positioning nor cursive connections, then Fontlab is enough. However, if the Arabic font needs to work on all Microsoft applications and Adobe Applications beside having dynamic mark positioning or cursive connections, then Volt alongside Fontlab in needed.

As for Macintosh (MacOS) system applications, then an AAT font tables are needed.
Apple system support for OpenType Layout does not include Arabic shaping support. Arabic shaping for the Mac can be implemented by using Apple’s own AAT font tables, but this requires independent development parallel to the OpenType development for Windows and Adobe applications. It also, at the moment, requires separate fonts for different platforms, because Apple has implemented OpenType Layout in a way that overrides AAT tables in the same font. So it is not currently possible to make fonts with both OTL and AAT tables and achieve best results on all platforms.
—————————————————————————————
—————————————————————————————
—————————————————————————————
—————————————————————————————

3. Arabic font Naming:

3.1 OpenType & TrueType font naming:

(http://www.kltf.de/downloads/FontNaming-kltf.pdf)
(http://just.letterror.com/ltrwiki/FontLab_2fFamilyNaming)

Refer to the links about Font Naming.

Below is a python script that does the naming for the font automatically.
Put in the proper naming and info within the correct place in the script and then run it with Robofab in Fontlab. The following script was written by my colleague Gustavo Ferrera.

—————————————————————————————
from robofab.world import CurrentFont

f = CurrentFont()

# font info:

familyName = ‘FontName’
styleName = ‘FontStyle’

designer = “designe’sr name”
designerURL = “designer’s url”
year = 20??
copyright = “Copyright ” + str(year) + ” ” + str(designer) +”.”
#vendor = “vendor’s name”
#vendorURL = “vendor’s url”
#trademark = “”
#notice = “add notice”
#license = “insert license here…”
#licenseURL = “http://??????/??????/license/”

# set font info:

def fullName():

if styleName == ‘Regular’:
fullName = familyName

else:
fullName = familyName + ‘ ‘ + styleName

return fullName

def fontName():

if styleName == ‘Regular’:
fontName = familyName

else:
fontName = familyName + ‘-’ + styleName

return fontName

f.info.familyName = familyName
f.info.styleName = styleName
f.info.fullName = fullName()
f.info.fontName = fontName()
f.info.menuName = familyName
f.info.fondName = fullName()
f.info.otFamilyName = familyName
f.info.otStyleName = styleName

f.info.ttUniqueID = designer + “: ” + fullName() + “: ” + str(year)

f.info.year = year
f.info.createdBy = designer
f.info.designer = designer
f.info.designerURL = designerURL
#f.info.vendorURL = vendorURL
#f.info.ttVendor = vendor
f.info.copyright = copyright
#f.info.trademark = trademark
#f.info.license = license
#f.info.licenseURL = licenseURL
#f.info.notice = notice

f.update()

# print font info:

print “familyName:”, f.info.familyName
print “styleName:”, f.info.styleName
print “fullName: “, f.info.fullName
print “menuName:”, f.info.menuName
print “fondName:”, f.info.fondName
print “otFamilyName:”, f.info.otFamilyName
print “osStyleName:”, f.info.otStyleName
print
print “ttUniqueID:”, f.info.ttUniqueID
print
print “year:”, f.info.year
print “createdBy:”, f.info.createdBy
print “designer:”, f.info.designer
print “designerURL”, f.info.designerURL
print “vendorURL:”, f.info.vendorURL
print “vendor:”, f.info.ttVendor
print “copyright:”, f.info.copyright
print “trademark:”, f.info.trademark
print “license:”, f.info.license
print “licenseURL:”, f.info.licenseURL
print “notice:”, f.info.notice
print
—————————————————————————————
—————————————————————————————

3.2 Arabic AXt font naming:

For AXt fonts it is the same naming technique as any postscript font but the three letters (AXt) (Capital ‘A’, Capital ‘X’ and lowercase ‘t’) must be added at the beginning and there should be no spaces in the name of the font. (AXtFontName)

—————————————————————————————
—————————————————————————————
—————————————————————————————
—————————————————————————————

4. Arabic font Formats:

For Adobe & Microsoft: OpenType Arabic fonts
For QuarkAXt 6.5 and privious versions: PostScript Suit fonts
For MacOS: AAT fonts

—————————————————————————————
—————————————————————————————
—————————————————————————————
—————————————————————————————

This Article is based on my own experience with generating Arabic fonts and with the help of other type designer. i would like to thank: Erik van Blokland, John Hudson, Nadine Chahine, Thomas Milo, Peter Bilak, Joe Abi Raad (Layout ltd) , Frederik Frelaen and Gustavo Ferreira.

Any kind of comment or opinion concerning this topic will be most welcomed.
Any Additional info about Generating Arabic fonts is also welcomed.

Pascal Zoghbi, May 2007.