% language=uk \usetypescriptfile[type-husayni] \startcomponent hybrid-goodies \environment hybrid-environment % this will change \definefontfeature [husayni-none] [analyze=yes,mode=node, language=dflt,script=arab, ccmp=yes] \definefontfeature [husayni-default] [analyze=yes,mode=node, language=dflt,script=arab, ccmp=yes,init=yes,medi=yes,fina=yes, rlig=yes,calt=yes,salt=yes,anum=yes, kern=yes,curs=yes,mark=yes,mkmk=yes, ss01=yes,ss03=yes,ss10=yes,ss12=yes,ss15=yes,ss16=yes, ss19=yes,ss24=yes,ss25=yes,ss26=yes,ss27=yes,ss31=yes, ss34=yes,ss35=yes,ss36=yes,ss37=yes,ss38=yes,ss41=yes, ss43=yes] \definefontfeature [husayni-first-order] [script=arab,ss01=yes,ss03=yes,ss05=yes, ss10=yes,ss12=yes,ss15=yes,ss16=yes,ss19=yes,ss24=yes, ss25=yes,ss26=yes,ss27=yes,ss31=yes,ss34=yes,ss35=yes, ss36=yes,ss37=yes,ss38=yes,ss41=yes,ss42=yes,ss43=yes] \definefontfeature [husayni-stack-jiim-multi-level] [script=arab,ss05=yes] \definefontfeature [husayni-minimal-stretching] [script=arab, ss05=yes,ss09=yes,ss06=yes,ss13=yes,ss17=yes,ss40=yes, js11=yes,js14=yes,js16=yes] \definefontfeature [husayni-maximal-stretching] [script=arab, ss05=yes,ss09=yes,ss06=yes,ss13=yes,ss17=yes,ss40=yes, js13=yes,js14=yes,js16=yes] \definefontfeature [husayni-chop-haa] [script=arab, ss05=yes,ss09=yes,ss06=yes,ss13=yes,ss17=yes,ss54=yes] \definefontfeature [husayni-normal] [goodies=husayni, featureset=default] \definefont[ArabicFontNone][husayni*husayni-none at 40pt] \definefont[ArabicFontFull][husayni*husayni-default at 40pt] % husayni-normal \startchapter[title={Font Goodies}] \startsection[title={Introduction}] The Oriental \TEX\ project is one of the first and more ambitious users of \LUATEX. A major undertaking in this project is the making of a rather full features and complex font for typesetting Arabic. As the following text will show some Arabic, you might get the impression that I'm an expert but be warned that I'm far from that. But as Idris compensates this quite well the team has a lot of fun in figuring out how to achieve our goals using \OPENTYPE\ technology in combination with \LUATEX\ and \MKIV. A nice side effect of this is that we end up with some neat tricks in the \CONTEXT\ core. Before we come to some of these goodies, an example of Arabic is given that relates quite well to the project. It was first used at the euro\TEX\ 2009 meeting. Take the following 6 shapes: \starttabulate[|c|c|c|c|c|c|] \NC \ArabicFontFull ل \NC \ArabicFontFull و \NC \ArabicFontFull ا \NC \ArabicFontFull ت \NC \ArabicFontFull ي \NC \ArabicFontFull خ \NC \NR \NC \type{l} \NC \type{w} \NC \type{ā} \NC \type{t} \NC \type{ī} \NC \type{kh} \NC \NR \stoptabulate With these we can make the name \LUATEX\ and as we use a nice script we can forget about the lowered~E. Putting these characters in sequence is not enough as Arabic typesetting has to mimick the subtle aspects of scribes. In Latin scripts we have mostly one|-|to|-|one and many|-|to|-|one substitutions. These can happen in sequence which in in practice boils down to multiple passes over the stream of characters. In this process sometimes surrounding characters (or shapes) play a role, for instance ligatures are not always wanted and their coming into existence might depend on neighbouring characters. In some cases glyphs have to be (re)positioned relative to each other. While in Latin scripts the number of substitutions and positioning is not that large but in advanced Arabic fonts it can be pretty extensive. With \OPENTYPE\ we have some machinery available, so we try to put as much logic in the font as possible. However, in addition we have some dedicated optimizing routines. The whole process is split into a couple if stages. The so called First|-|Order Analysis puts a given character into isolated, initial, middle, or final state. Next, the Second|-|Order Analysis looks at the characters and relates this state to what characters precede or succeed it. Based on that state we do character substitutions. There can be multiple analysis and replacements in sequence. We can do some simple aesthetic stretching and additional related replacements. We need to attach identity marks and vowels in proper but nice looking places. In most cases we're then done. Contrary to other fonts we don't use many ligatures but compose characters. The previous steps already give reasonable results and implementing it also nicely went along with the development of \LUATEX\ and \CONTEXT\ \MKIV. Currently we're working on extending and perfecting the font to support what we call Third|-|Order Contextual Analysis. This boils down to an interplay between the paragraph builder and additional font features. In order to get pleasing spacing we apply further substitutions, this time with wider or narrower shapes. When this is done we need to reattach identity marks and vowels. Optionally we can apply \HZ\ like stretching as a finishing touch but so far we didn't follow that route yet. So, let's see how we can typeset the word \LUATEX\ in Arabic using some of these techniques. \startlines no order (kh ī t ā w [u] l)\hfilll {\righttoleft\ArabicFontNone لُواتيخ} first order \hfilll {\subff{husayni-first-order}\righttoleft\ArabicFontFull لُواتيخ} second order \hfilll {\righttoleft\ArabicFontFull لُواتيخ} second order (Jiim-stacking) \hfilll {\addff{husayni-stack-jiim-multi-level}\righttoleft\ArabicFontFull لُواتيخ} minimal stretching \hfilll {\addff{husayni-minimal-stretching}\righttoleft\ArabicFontFull لُواتيخ} maximal stretching (level 3) \hfilll {\addff{husayni-maximal-stretching}\righttoleft\ArabicFontFull لُواتيخ} chopped letter khaa (for e.g.\ underlining) \hfilll {\addff{husayni-chop-haa}\righttoleft\ArabicFontFull لُواتيخ} \stoplines As said, this font is quite complex in the sense that it has many features and associated lookups. In addition to the usual features we have stylistic and justification variants. As these are not standardized (after all, each font can have its own look and feel and associated treatments) we store some information in the goodies files that ship with this font. \startbuffer[stylistics] \startluacode local goodies = fonts.goodies.load("husayni") local stylistics = goodies and goodies.stylistics if stylistics then local col, row, type = context.NC, context.NR, context.type context.starttabulate { "|l|pl|" } col() context("feature") col() context("meaning") col() row() for feature, meaning in table.sortedpairs(stylistics) do col() type(feature) col() type(meaning) col() row() end context.stoptabulate() end \stopluacode \stopbuffer \getbuffer[stylistics] It is highly unlikely that a user will remember all these features, which is why there will be a bunch of predefined combinations. These are internalized as follows: \startbuffer[featuresets] \startluacode local goodies = fonts.goodies.load("husayni") local featuresets = goodies and goodies.featuresets if featuresets then local col, row, type = context.NC, context.NR, context.type context.starttabulate { "|l|pl|" } col() context("featureset") col() context("definitions") col() row() for featureset, definitions in table.sortedpairs(featuresets) do col() type(featureset) col() for k, v in table.sortedpairs(definitions) do type(string.format("%s=%s",k,tostring(v))) context.quad() end col() row() end context.stoptabulate() end \stopluacode \stopbuffer \getbuffer[featuresets] \stopsection \startsection[title={Color}] One of the objectives of the oriental \TEX\ project is to bring color to typeset Arabic. When Idris started making samples with much manual intervention it was about time to figure out if it could be supported by a bit of \LUA\ code. As the colorization concerns classes of glyphs (like vowels) this is something that can best be done after all esthetics have been sorted out. Because things like coloring are not part of font technology and because we don't want to misuse the \OPENTYPE\ feature mechanisms for that, the solution lays in an extra file that describes these goodies. \startbuffer[goodies-1] \definefontfeature [husayni-colored] [goodies=husayni, colorscheme=default, featureset=default] \stopbuffer \startbuffer[goodies-2] \start \definedfont[husayni*husayni-colored at 72pt] \righttoleft \resetfontcolorscheme لُواتيخ ألف ليلة وليلة \par \setfontcolorscheme [1]لُواتيخ ألف ليلة وليلة \crlf \setfontcolorscheme [2]لُواتيخ ألف ليلة وليلة \crlf \stop \stopbuffer \getbuffer[goodies-1,goodies-2] The second and third of these three lines have colored vowels and identity marks. So how did we get the colors? There are actually two mechanisms involved in this: \startitemize[packed] \startitem we need to associate colorschemes with classed of glyphs \stopitem \startitem we need to be able to turn on and off coloring \stopitem \stopitemize The first is done by loading goodies and selecting a colorscheme: \typebuffer[goodies-1] Turning on and off coloring is done with two commands (we might provide a proper environment for this) as shown in: \typebuffer[goodies-2] If you look closely at the feature definition you'll notice that we also choose a default featureset. For most (latin) fonts the regular feature definitions are convenient, but for fonts that are used for Arabic there are preferred combinations of features as there can be many. Currently the font we use here has the following colorschemes: \startbuffer[colorschemes] \startluacode local goodies = fonts.goodies.load("husayni") local colorschemes = goodies and goodies.colorschemes if colorschemes then local col, row, type = context.NC, context.NR, context.type context.starttabulate { "|l|pl|" } col() context("colorscheme") col() context("numbers") col() row() for colorscheme, numbers in table.sortedpairs(colorschemes) do col() type(colorscheme) col() for i=1,#numbers do type(i) context.quad() end col() row() end context.stoptabulate() end \stopluacode \stopbuffer \getbuffer[colorschemes] \stopsection \startsection[title={The goodies file}] In principle a goodies files can contain anuy data that makes sense but in order to be useable some entries have a prescribed structure. A goodies file looks as follows: \starttyping return { name = "husayni", version = "1.00", comment = "Goodies that complement the Husayni font by Idris Samawi Hamid.", author = "Idris Samawi Hamid and Hans Hagen", featuresets = { default = { key = value,