These snippets are intended as a quick reference. For complete documentation of the GDL language, download the reference paper:
![]() | GDL Documentation Sharon Correll, 2020-05-21 Download "GDLdocumentation.pdf", Acrobat PDF document, 725KB [8361 downloads] |
table(glyph) // These can also be classes, in which case the attachment point(s) // must be defined on each element of the class: base = glyphid(34) {TopS = point(130m, 512m); BottomS = point(130m, 0m)}; upperdiac = glyphid(101) {TopM = point(86m, -12m)} lowerdiac = glyphid(102) {BottomM = point(86m, 43m)}; endtable; // glyph table(positioning) base upperdiac {attach {to=@1; at=TopS; with=TopM}}; base lowerdiac {attach {to=@1; at=BottomS; with=BottomM}}; endtable; // positioning
table(glyph) base = glyphid(...) {TopS = point(bb.lsb + bb.width/2, bb.top); BottomS = point(bb.lsb + bb.width/2, bb.bottom)}; upperdiac = glyphid(...) {TopM = point(bb.width/2, bb.bottom - 10m)} lowerdiac = glyphid(...) {BottomM = point(bb.width/2, bb.top + 10m)}; endtable; // glyph table(positioning) base upperdiac {attach {to=@1; at=TopS; with=TopM}}; base lowerdiac {attach {to=@1; at=BottomS; with=BottomM}}; endtable; // positioning
The following example shows how to handle a stack/chain of both upper and lower diacritic attachments. Note that, as specified by the Unicode standard, lower diacritics are first.
table(glyph) base1 = glyphid(34) {TopS = point(130m, 512m); BottomS = point(130m, 0m)}; base1 = glyphid(35) {TopS = point(130m, 5108m); BottomS = point(130m, -18m)}; upperdiac1 = glyphid(101) {TopM = point(86m, -12m); TopS = point(86m, 43m)}; upperdiac2 = glyphid(105) {TopM = point(81m, -10m); TopS = point(81m, 52m)}; lowerdiac1 = glyphid(102) {BottomM = point(79m, 43m); BottomS = point(79m, -3m)}; lowerdiac2 = glyphid(103) {BottomM = point(77m, 48m); BottomS = point(77m, -5m)}; // etc. base = (base1, base2, ...); upperdiac = (upperdiac1, upperdiac2, ...); lowerdiac = (lowerdiac1, lowerdiac2, ...); takes_lower = (base, lowerdiac); // lower diacritics can be attached to bases or other lower diacs takes_upper = (base, upperdiac); // upper diacritics can be attached to bases or other upper diacs endtable; // glyph table(positioning) // Optionally permit up to three intervening lower diacritics: #define LOWERSEQ [ lowerdiac [ lowerdiac lowerdiac? ]? ]? takes_lower lowerdiac {attach {to=@1; at=BottomS; with=BottomM}} / _ ^ _; takes_upper upperdiac {attach {to=@1; at=TopS; with=TopM}} / _ LOWERSEQ ^ _; endtable; // positioning
Bridging diacritics must be centered over the two bases they bridge and must be higher than the tallest.
table(glyph) base1 = ...; base2 = ...; bridgediac = ...; endtable; // glyph table(positioning) bridgediac {shift.y = max(@B1.boundingbox.top, @B2.boundingbox.top) - @D.boundingbox.bottom + 100m ; // gap of 100m shift.x = (@B2.boundingbox.width - @B1.boundingbox.width)/2} / base1=B1 _=D base2=B2; endtable; // positioning
If the base glyphs have other diacritics attached, using @B1.boundingbox.top.1 will give the bounding box of the base plus diacritics.
Ligatures or conjuncts occur when multiple characters combine to form a single glyph shape.
table(glyph) char1 = ...; char2 = ...; ligature = ...; endtable; // glyph table(substitution) char1 char2 > ligature:(1 2) _ ; endtable; // substitution
Ligature components correspond to sub-regions of the ligature glyph that visually correspond to the original characters. Selecting and manipulating the visual components allows manipulating the underlying characters.
Note
This feature is only supported by the original Graphite engine; it is not supported by Graphite2.
table(glyph) char1 = ...; char2 = ...; ligature = ... // <-- specify which glyph // Define the visual components of the conjunct. // This conjunct has three components: // the top-left, the bottom-left, and the right side. { component {cTL= box(0, bb.height/2, aw/2, bb.top); cBL= box(0, bb.bottom, aw/2, bb.height/2); cR = box(aw/2, bb.bottom, aw, bb.top) } }; endtable; // glyph table(substitution) char1 char2 char3 > ligature:(1 2 3) {component {cTL.ref=@1; cBL.ref=@2; cR=@3}} _ _; endtable; // substitution
Many scripts have characters that must use alternate forms depending on neighboring letters.
table(glyph) // Define the glyphs and classes: matraI = ...; matraI_wide = ...; matraI_wider = ...; matraI_widest = ...; class_wide = ...; class_wider = ...; class_widest = ...; endtable; // glyph table(substitution) // Choose the width of the matra-I that matches the width of the neighboring letter: matraI class_wide > matraI_wide @2; matraI class_wider > matraI_wider @2; matraI class_widest > matraI_widest @2; endtable;
Arabic is an example of a script whose characters take on alternate forms depending on their location within the word: initial, medial, final, isolate.
table(glyph) // All characters are initially isolate forms. // Define the individual glyphs: beh = ...; behInit = ...; // etc. // Elements of these four classes must correspond: class_isolate = (beh, teh, theh, peh, teheh, ...); class_initial = (behInit, tehInit, thehInit, pehInit, tehehInit, ...); class_medial = (behMed, behMed, thehMed, pehMed, tehehMed, ...); class_final = (behFin, behFin, thehFin, pehFin, tehehFin, ...); endtable; // glyph table(substitution) // For any contiguous pair of word-forming letters: // turn the first from isolate to initial, or from final to medial // turn the second to final // back up and treat the second as the first of the next pair to consider // Any unprocessed letters are left as isolates. (class_isolate class_final) (class_isolate) > (class_initial class_medial) (class_final) / _ ^ _; endtable; // substitution
Many scripts of south and southeast Asia have characters that are rendered in an order that is different from their order in the data.
table(glyph) // Define the glyphs or classes: consonants = ...; vowelLeftSide = ...; endtable; // glyph table(substitution) consonant vowelLeftSide > @2 @1; endtable; // substitution
Many scripts of south and southeast Asia have characters that are rendered by two or more non-contiguous glyphs.
table(glyph) // Define the glyphs or classes: consonants = ...; // If these are classes, the elements of the classes must correspond: vowelSplit = (vowel1, vowel2, vowel3, ...); vowelLeftHalf = (vowel1Left, vowel2Left, vowel3Left, ...); vowelRightHalf = (vowel1Right, vowel2Right, vowel3Right, ...); endtable; // glyph table(substitution) _ consonant vowelSplit > vowelLeftHalf$3:3 @2 vowelRightHalf:3; end-table; // substitution
Font features provide a way to define alterative renderings that can be selected by the user.
table(feature) altk { id = "altk"; // can be integer or 4-char string name.1033 = string("Alternate K"); // 1033 = LG_USENG, US English default = 0; settings { off { value = 0; name.1033 = string("False"); } on { value = 1; name.1033 = string("True"); } } }; endtable; // feature table(glyph) g_k = ...; g_k_alt = ...; endtable; // glyph table(substitution) if (altk) g_k > g_k_alt endif; endtable; // substitution
table(feature) altk { id = "altk"; // can be integer or 4-char string name.1033 = string("Alternate K"); // 1033 = LG_USENG, US English default = 0; settings { form1 { value = 0; name.1033 = string("Form 1"); } form2 { value = 1; name.1033 = string("Form 2"); } form3 { value = 2; name.1033 = string("Form 3"); } form4 { value = 3; name.1033 = string("Form 4"); } } }; endtable; // feature table(glyph) g_k = ...; g_k1 = ...; g_k2 = ...; g_k3 = ...; g_k4 = ...; endtable; // glyph table(substitution) // Note that for mutually exclusive conditions, successive 'if' statements are more efficient than 'elseif'. if (altk == form1) g_k > g_k1; endif; if (altk == form2) g_k > g_k2; endif; if (altk == form3) g_k > g_k3; endif; if (altk == form4) g_k > g_k3; endif; endtable; // substitution
Copyright © 2012 SIL International® and released under the Creative Commons Attribution-ShareAlike 3.0 license (CC-BY-SA) unless noted otherwise.