├── Slabikar.otf ├── examples ├── tex │ ├── example.pdf │ ├── reference │ │ ├── example1.png │ │ └── example2.png │ ├── compare.py │ └── example.tex ├── python │ └── example.py └── html │ └── example.html ├── update_gh_pages.sh ├── environment.yml ├── font.ufo ├── metainfo.plist ├── layercontents.plist ├── fontinfo.plist └── features.fea ├── gen ├── glif2svg.py ├── svg2glif.py ├── bezier.py ├── glif.py └── svg.py ├── LICENSE ├── README.md └── .github └── workflows └── CI.yml /Slabikar.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certik/slabikar-otf/HEAD/Slabikar.otf -------------------------------------------------------------------------------- /examples/tex/example.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certik/slabikar-otf/HEAD/examples/tex/example.pdf -------------------------------------------------------------------------------- /examples/tex/reference/example1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certik/slabikar-otf/HEAD/examples/tex/reference/example1.png -------------------------------------------------------------------------------- /examples/tex/reference/example2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/certik/slabikar-otf/HEAD/examples/tex/reference/example2.png -------------------------------------------------------------------------------- /update_gh_pages.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -ex 4 | 5 | mkdir docs2 6 | cp Slabikar.otf docs2/ 7 | cp examples/html/example.html docs2/index.html 8 | git checkout gh-pages 9 | rm -rf docs 10 | mv docs2 docs 11 | -------------------------------------------------------------------------------- /environment.yml: -------------------------------------------------------------------------------- 1 | name: fonts 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - python=3.10 6 | - pip 7 | - tectonic=0.9.0 8 | - numpy=1.23.2 9 | - pillow=9.2.0 10 | - ghostscript=9.54.0 11 | - pip: 12 | - afdko==3.9.1 13 | -------------------------------------------------------------------------------- /font.ufo/metainfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | formatVersion 6 | 3 7 | 8 | 9 | -------------------------------------------------------------------------------- /font.ufo/layercontents.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | public.default 7 | glyphs 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /gen/glif2svg.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from glif import parse_glif, glif2svg 4 | 5 | if len(sys.argv) != 2: 6 | print("glif2svg filename") 7 | sys.exit(1) 8 | 9 | filename_in = sys.argv[1] 10 | filename_out_svg = os.path.splitext(os.path.basename(filename_in))[0] + ".svg" 11 | print(f"{filename_in} -> {filename_out_svg}") 12 | g = parse_glif(open(filename_in).read()) 13 | open(filename_out_svg, "w").write(glif2svg(g, False, True, 0.0)) 14 | -------------------------------------------------------------------------------- /gen/svg2glif.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from glif import parse_svg, glif2svg, glif2glif 4 | 5 | if len(sys.argv) != 2: 6 | print("svg2glif filename") 7 | sys.exit(1) 8 | 9 | filename_in = sys.argv[1] 10 | filename_out_svg = os.path.splitext(os.path.basename(filename_in))[0] + "_out3.svg" 11 | print(f"{filename_in} -> {filename_out_svg}") 12 | g = parse_svg(open(filename_in).read()) 13 | open(filename_out_svg, "w").write(glif2svg(g, False, True, 0.0)) 14 | 15 | filename_out_glif = os.path.splitext(os.path.basename(filename_in))[0] + "_out3.glif" 16 | print(f"{filename_in} -> {filename_out_glif}") 17 | g = parse_svg(open(filename_in).read()) 18 | open(filename_out_glif, "w").write(glif2glif(g)) 19 | -------------------------------------------------------------------------------- /examples/tex/compare.py: -------------------------------------------------------------------------------- 1 | from PIL.Image import open 2 | from PIL.ImageChops import difference 3 | 4 | def images_equal(img1, img2, diff): 5 | d = difference(open(img1), open(img2)) 6 | if d.getbbox(): 7 | d.save(diff) 8 | # Images not equal 9 | return False 10 | else: 11 | # Images equal 12 | return True 13 | 14 | if __name__ == '__main__': 15 | r1 = images_equal("example1.png", "reference/example1.png", "diff1.png") 16 | r2 = images_equal("example2.png", "reference/example2.png", "diff2.png") 17 | if r1 and r2: 18 | print("Images equal") 19 | else: 20 | print("Images NOT equal") 21 | raise Exception("Images not equal") 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Ondřej Čertík 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Slabikář Font 2 | 3 | This is an OpenType font (OTF) version of the Slabikář font from Petr Olšák: 4 | 5 | http://petr.olsak.net/ftp/olsak/slabikar/ 6 | 7 | The `Slabikar.otf` font works in LaTeX, HTML, system-wide and it should work on 8 | any system and program that works with OTF fonts. 9 | 10 | # Examples 11 | 12 | * LaTeX: [example.tex](./examples/tex/example.tex) ([example.pdf](./examples/tex/example.pdf)) 13 | * Online demo: https://certik.github.io/slabikar-otf/ 14 | 15 | # Build Instructions 16 | 17 | To build the `Slabikar.otf` font from source: 18 | ``` 19 | conda env create -f environment.yml 20 | conda activate fonts 21 | ./build.sh 22 | ``` 23 | 24 | To install system-wide on macOS, do: 25 | ``` 26 | cp Slabikar.otf ~/Library/Fonts 27 | ``` 28 | Then open up some text editor, such as Pages, and select the font 29 | "Slabikář" and use it. Similarly on other systems. 30 | 31 | 32 | # License 33 | 34 | The Slabikář font shapes were created by Petr Olšák in Metafont and copyrighted 35 | by him. 36 | 37 | All the files in this repository were created by Ondřej Čertík and are licensed 38 | under the MIT license, see [LICENSE](./LICENSE) file for more information. 39 | -------------------------------------------------------------------------------- /examples/python/example.py: -------------------------------------------------------------------------------- 1 | """ 2 | Pillow has ImageFont for rendering text: 3 | 4 | https://pillow.readthedocs.io/en/stable/reference/ImageFont.html 5 | 6 | If Pillow is compiled without "RAQM" support, it can only print the glyphs from 7 | `Slabikar.otf`, but does not execute/interpret the GSUB/GPOS tables, so the 8 | beginning, end and middle connections are missing. 9 | 10 | In order to get the proper text, we have to use Pillow with RAQM. To be 11 | specific, the FreeType [1] library only handles glyph drawing, the HarfBuzz 12 | library handles "text shaping" (the GSUB/GPOS tables in the OTF font) and 13 | finally the RAQM [3] library provides a convenient API to FreeType+HarfBuzz. 14 | 15 | [1] https://freetype.org/ 16 | [2] https://harfbuzz.github.io/ 17 | [3] https://github.com/HOST-Oman/libraqm 18 | """ 19 | import PIL.features 20 | if not PIL.features.check_feature("raqm"): 21 | print("Warning: RAQM support is missing, the font will be incorrectly connected") 22 | from PIL import Image, ImageFont, ImageDraw 23 | antialiasing = True 24 | scale=1 25 | image = Image.new(mode="L" if antialiasing else "1", 26 | size=(80*scale, 33*scale), color="white") 27 | draw = ImageDraw.Draw(image) 28 | font = ImageFont.truetype("../../Slabikar.otf", 50*scale) 29 | draw.text((3*scale, 2*scale), "Psát", font=font, fill='black') 30 | image.save("font.png") 31 | -------------------------------------------------------------------------------- /gen/bezier.py: -------------------------------------------------------------------------------- 1 | from numpy import array, sqrt, arctan2, sin, cos 2 | 3 | def arg(z): 4 | # NumPy's arctan2(y,x) is equal to the arg(x,y) before equation (2) in [1] 5 | return arctan2(z[1], z[0]) 6 | 7 | def compute_control_points(z1, z2, w1, w2, tau): 8 | """ 9 | z1, z2 ... the Bezier nodes (1st and 4th control point) 10 | w1, w2 ... tangent vectors (do not have to be unit vectors), just direction 11 | tau ... tension (0.75 .. oo) 12 | 13 | The formulas are implemented from [1], equations (3) and (10). 14 | 15 | Note: the unit tangent vector always points along the direction of the 16 | curve, so the first point "in" the curve, but the second points "out". 17 | 18 | [1] John D. Hobby: Smooth, Easy to Compute Interpolating Splines. 1985. CS-TR-85-1047. 19 | Online link: http://i.stanford.edu/pub/cstr/reports/cs/tr/85/1047/CS-TR-85-1047.pdf 20 | """ 21 | z1 = array(z1) 22 | z2 = array(z2) 23 | tau1 = tau2 = tau 24 | 25 | # Metafont parameters, paragraph after (10) in [1] 26 | a = sqrt(2) 27 | b = 1/16 28 | c = (3-sqrt(5))/2 29 | 30 | # Paragraph above equation (2) in [1] 31 | theta = arg(w1) - arg(z2-z1) 32 | phi = arg(z2-z1) - arg(w2) 33 | 34 | # Equations (10) in [1] 35 | alpha = a * (sin(theta) - b*sin(phi)) * (sin(phi) - b*sin(theta)) \ 36 | * (cos(theta) - cos(phi)) 37 | rho = (2 + alpha) / (1 + (1-c)*cos(theta) + c*cos(phi )) 38 | sigma = (2 - alpha) / (1 + (1-c)*cos(phi ) + c*cos(theta)) 39 | 40 | # Paragraph above equation (3) in [1] 41 | c1 = rho/(3*tau1) * array([cos(theta), sin(theta)]) 42 | c2 = array([1 - sigma/(3*tau2) * cos(phi), sigma/(3*tau2) * sin(phi)]) 43 | 44 | # Shift and rotate the control points from (0,0)-(1,0) to z1-z2; equation (2) in [1] 45 | c1 = z1 + array([ 46 | (z2[0]-z1[0])*c1[0]+(z1[1]-z2[1])*c1[1], 47 | (z2[1]-z1[1])*c1[0]+(z2[0]-z1[0])*c1[1] 48 | ]) 49 | c2 = z1 + array([ 50 | (z2[0]-z1[0])*c2[0]+(z1[1]-z2[1])*c2[1], 51 | (z2[1]-z1[1])*c2[0]+(z2[0]-z1[0])*c2[1] 52 | ]) 53 | 54 | return c1, c2 55 | -------------------------------------------------------------------------------- /examples/tex/example.tex: -------------------------------------------------------------------------------- 1 | \documentclass{article} 2 | \usepackage[a4paper, margin=1in]{geometry} 3 | \usepackage{fontspec} 4 | 5 | 6 | \begin{document} 7 | 8 | \fontsize{25pt}{30pt} 9 | \fontspec{Slabikar.otf} 10 | 11 | \noindent A--- písmeno pro tebe,\\ 12 | anděl letí do nebe,\\ 13 | Andělka mu štěstí přála\\ 14 | a šátečkem zamávala,\\ 15 | aby neulét\\ 16 | a vrátil se zpět.\\ 17 | 18 | \noindent Digits: 1234567890\\ 19 | Punctuation: !?,.:;'" a-a a--a a---a\\ 20 | Other: +-×*=/\textbackslash <>@()[]\{\}\%\&\$\#\^{}|\~{}\_‰\\ 21 | "x" 'x' „x“\\ 22 | aáäbcčdďeéěfghiíjklĺľmnňoóôpqrřŕsštťuúůvwxyýzž\\ 23 | AÁÄBCČDĎEÉĚFGHIÍJKLĹĽMNŇOÓÔPQRŘŔSŠTŤUÚŮVWXYÝZŽ\\ 24 | As Ás Äs Bs Cs Čs Ds Ďs Es És Ěs Fs Gs Hs Is Ís Js Ks Ls Ĺs Ľs Ms Ns Ňs Os Ós Ôs Ps Qs Rs Řs Ŕs Ss Šs Ts Ťs Us Ús Ůs Vs Ws Xs Ys Ýs Zs Žs\\ 25 | 26 | 27 | \def\TeX{T\kern-.28em\lower.7ex\hbox{E}\kern-.17emX} 28 | \righthyphenmin=2 \emergencystretch=2em 29 | \hbadness=2900 30 | 31 | Toto písmo je potřeba brát spíš jako příklad, co všechno \TeX{} dovede. 32 | Nepředpokládám velké nasazení tohoto písma pro sazbu příštích 33 | slabikářů. Dokonce takovou věc ani nedoporučuji. 34 | 35 | Všechny ukázky ve slabikáři a v~písankách, které jsem měl možnost vidět, 36 | jsou psány lidskou rukou a ne strojem. Samozřejmě smekám před kaligrafem, 37 | který ty ukázky vytvořil. Člověk má na první pohled dojem, že to je 38 | „jak když tiskne“. Fušoval jsem také do kaligrafického řemesla, a proto 39 | dobře vím, že pokud písmo neobsahuje žádné ozdobné prvky, musí to napsat 40 | skutečně profesionál. Každá chybička, která by se třeba skryla za ozdobným 41 | prvkem, je totiž vidět. 42 | 43 | Důležité ale je, že písmo v~dnešním slabikáři bylo skutečně napsáno jen 44 | „jak“ když tiskne a nikoli tištěno doopravdy. Písmu tak neschází 45 | lidský rozměr, který ten prvňák podvědomě z~toho písma asi cítí. Kdyby se 46 | pro sazbu ukázek použil stroj (třebaže~\TeX), písmo by tento rozměr 47 | ztratilo. Takové písmo by bylo chladné, stále stejné, bez výrazu, 48 | tedy vlastně mrtvé. Nepřeji prvňákům, aby se někdy v~budoucnu 49 | s~takovým chladným písmem setkali. 50 | 51 | \medskip 52 | \hfill Petr Olšák 53 | 54 | 55 | \end{document} 56 | -------------------------------------------------------------------------------- /examples/html/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 25 | 26 | 27 |

Slabikář Font

28 | Download: Slabikar.otf
29 | Source code: https://github.com/certik/slabikar-otf
30 | You can edit the text below to play with the font:
31 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /.github/workflows/CI.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | tags: 8 | - 'v*' 9 | pull_request: 10 | branches: 11 | - main 12 | 13 | 14 | jobs: 15 | Build: 16 | name: Tectonic 17 | runs-on: ubuntu-latest 18 | strategy: 19 | fail-fast: false 20 | steps: 21 | - uses: actions/checkout@v2 22 | with: 23 | fetch-depth: 0 24 | 25 | - name: Install Inkscape in Ubuntu 26 | run: | 27 | sudo add-apt-repository ppa:inkscape.dev/stable 28 | sudo apt update 29 | sudo apt -y install inkscape 30 | sudo touch /var/lib/cloud/instance/locale-check.skip 31 | 32 | - uses: mamba-org/provision-with-micromamba@main 33 | with: 34 | environment-file: environment.yml 35 | extra-specs: | 36 | python=3.10 37 | 38 | - uses: hendrikmuhs/ccache-action@main 39 | with: 40 | variant: sccache 41 | key: ${{ github.job }} 42 | 43 | - name: Build 44 | shell: bash -l {0} 45 | run: | 46 | ./build.sh 47 | 48 | - name: Archive artifacts 49 | if: always() 50 | uses: actions/upload-artifact@v3 51 | with: 52 | name: results 53 | path: | 54 | Slabikar.otf 55 | examples/tex/example.pdf 56 | examples/tex/example1.png 57 | examples/tex/example2.png 58 | examples/tex/diff1.png 59 | examples/tex/diff2.png 60 | 61 | xelatex: 62 | name: xelatex 63 | runs-on: ubuntu-latest 64 | strategy: 65 | fail-fast: false 66 | steps: 67 | - uses: actions/checkout@v2 68 | with: 69 | fetch-depth: 0 70 | 71 | - name: Install Inkscape in Ubuntu 72 | run: | 73 | sudo add-apt-repository ppa:inkscape.dev/stable 74 | sudo apt update 75 | sudo apt -y install inkscape texlive-latex-extra texlive-xetex 76 | sudo touch /var/lib/cloud/instance/locale-check.skip 77 | 78 | - uses: mamba-org/provision-with-micromamba@main 79 | with: 80 | environment-file: environment.yml 81 | extra-specs: | 82 | python=3.10 83 | 84 | - uses: hendrikmuhs/ccache-action@main 85 | with: 86 | variant: sccache 87 | key: ${{ github.job }} 88 | 89 | - name: Build 90 | shell: bash -l {0} 91 | run: | 92 | ./build.sh 93 | 94 | - name: LaTeX 95 | shell: bash -l {0} 96 | run: | 97 | cd examples/tex 98 | rm example.pdf 99 | xelatex example.tex 100 | 101 | - name: Archive example.pdf 102 | if: always() 103 | uses: actions/upload-artifact@v3 104 | with: 105 | name: example_xelatex.pdf 106 | path: examples/tex/example.pdf 107 | -------------------------------------------------------------------------------- /font.ufo/fontinfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ascender 6 | 712 7 | capHeight 8 | 656 9 | copyright 10 | Copyright 2022 Ondřej Čertík, Petr Olšák 11 | descender 12 | -205 13 | familyName 14 | Slabikář 15 | guidelines 16 | 17 | 18 | italicAngle 19 | 0 20 | openTypeHheaAscender 21 | 1024 22 | openTypeHheaDescender 23 | -400 24 | openTypeHheaLineGap 25 | 0 26 | openTypeNameDesigner 27 | Petr Olšák 28 | openTypeNameLicense 29 | All files are licensed under the MIT license. 30 | openTypeNameLicenseURL 31 | https://opensource.org/licenses/MIT 32 | openTypeOS2CodePageRanges 33 | 34 | 0 35 | 1 36 | 2 37 | 3 38 | 4 39 | 7 40 | 8 41 | 29 42 | 43 | openTypeOS2Panose 44 | 45 | 2 46 | 11 47 | 5 48 | 3 49 | 3 50 | 4 51 | 3 52 | 2 53 | 2 54 | 4 55 | 56 | openTypeOS2TypoAscender 57 | 750 58 | openTypeOS2TypoDescender 59 | -250 60 | openTypeOS2TypoLineGap 61 | 0 62 | openTypeOS2UnicodeRanges 63 | 64 | 0 65 | 1 66 | 2 67 | 4 68 | 5 69 | 6 70 | 7 71 | 9 72 | 29 73 | 30 74 | 32 75 | 57 76 | 77 | openTypeOS2WinAscent 78 | 984 79 | openTypeOS2WinDescent 80 | 273 81 | postscriptBlueFuzz 82 | 0 83 | postscriptBlueScale 84 | 0.0625 85 | postscriptBlueValues 86 | 87 | -12 88 | 0 89 | 486 90 | 498 91 | 518 92 | 530 93 | 574 94 | 586 95 | 638 96 | 650 97 | 656 98 | 668 99 | 712 100 | 724 101 | 102 | postscriptFamilyBlues 103 | 104 | -12 105 | 0 106 | 486 107 | 498 108 | 518 109 | 530 110 | 574 111 | 586 112 | 638 113 | 650 114 | 656 115 | 668 116 | 712 117 | 724 118 | 119 | postscriptFamilyOtherBlues 120 | 121 | -217 122 | -205 123 | 124 | postscriptFontName 125 | Slabikar 126 | postscriptOtherBlues 127 | 128 | -217 129 | -205 130 | 131 | postscriptStemSnapH 132 | 133 | 67 134 | 78 135 | 136 | postscriptStemSnapV 137 | 138 | 84 139 | 95 140 | 141 | postscriptUnderlinePosition 142 | -75 143 | postscriptUnderlineThickness 144 | 50 145 | styleName 146 | Regular 147 | unitsPerEm 148 | 1000 149 | versionMajor 150 | 1 151 | versionMinor 152 | 0 153 | xHeight 154 | 486 155 | 156 | 157 | -------------------------------------------------------------------------------- /gen/glif.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from xml.etree.ElementTree import Element, tostring, fromstring, indent 3 | 4 | # Abstract Semantic Representation of the Glif format: 5 | 6 | @dataclass 7 | class Point: 8 | x: int 9 | y: int 10 | type: str 11 | smooth: bool 12 | 13 | @dataclass 14 | class Anchor: 15 | x: int 16 | y: int 17 | name: str 18 | 19 | @dataclass 20 | class Glif: 21 | name: str 22 | unicode_hex: str 23 | w: int 24 | contours: list[list[Point]] 25 | anchors: list[Anchor] 26 | 27 | # Verify 28 | 29 | def require(cond, msg): 30 | if not cond: 31 | raise Exception(msg) 32 | 33 | # TODO: verify "smooth" for each point as well. Give an error for 34 | # smooth=yes that is not smooth; and a warning for not defined smooth parameter 35 | # if it is smooth 36 | def verify_contour(contour: list[Point]): 37 | debug_print = False 38 | for n, point in enumerate(contour): 39 | require(isinstance(point.x, (int,float)), "Point.x must be integer") 40 | require(isinstance(point.y, (int,float)), "Point.y must be integer") 41 | require(point.type in ["curve", "offcurve", "line", "move"], 42 | "Point.type is not correct") 43 | if n > 0: 44 | require(point.type != "move", 45 | "Point.type cannot be move for n > 0") 46 | if len(contour) > 0: 47 | p = contour[0] 48 | # UFO 3 allows to start with any point (even offcurve), but we further 49 | # restrict it to always start with a line or curve, which simplifies 50 | # the writers. 51 | require(p.type in ["curve", "line", "move"], 52 | "The contour must start with a curve or line") 53 | if p.type == "move": 54 | require(contour[-1].type in ["curve", "line"], 55 | "Open contour must end with curve or line") 56 | else: 57 | contour = contour + [p] 58 | # The previous point type: 59 | # 0 ... line node (line) 60 | # 1 ... 1st curve point (offcurve) 61 | # 2 ... 2nd curve point (offcurve) 62 | # 3 ... 3rd curve point (curve) 63 | if p.type in ["line", "move"]: 64 | last_point_type = 0 65 | else: 66 | assert p.type == "curve" 67 | last_point_type = 3 68 | if debug_print: 69 | print(p, "'first point'") 70 | for p in contour[1:]: 71 | if debug_print: 72 | print(p, last_point_type) 73 | if p.type == "line": 74 | require(last_point_type in [0,3], 75 | "the last point before line must be line or curve") 76 | last_point_type = 0 77 | elif p.type == "curve": 78 | require(last_point_type == 2, 79 | "the last point before curve must be second offcurve point") 80 | last_point_type = 3 81 | else: 82 | assert p.type == "offcurve" 83 | require(last_point_type != 2, 84 | "three offcurve points in a row are not allowed") 85 | if last_point_type in [0, 3]: 86 | # First offcurve point 87 | last_point_type = 1 88 | else: 89 | # Second offcurve point 90 | assert last_point_type == 1 91 | last_point_type = 2 92 | 93 | 94 | def verify(glif: Glif): 95 | if glif.w is not None: 96 | require(isinstance(glif.w, (int,float)), "w must be integer") 97 | require(isinstance(glif.name, str), "name must be str") 98 | for contour in glif.contours: 99 | verify_contour(contour) 100 | 101 | # Reader for Glif: 102 | 103 | def num(x): 104 | try: 105 | return int(x) 106 | except ValueError: 107 | return float(x) 108 | 109 | def parse_glif(glif: str) -> Glif: 110 | glif = fromstring(glif) 111 | name = glif.get("name") 112 | if glif.find("advance") is not None: 113 | w = int(glif.find("advance").get("width")) 114 | else: 115 | w = None 116 | if glif.find("unicode") is not None: 117 | unicode_hex = glif.find("unicode").get("hex") 118 | else: 119 | unicode_hex = None 120 | contours = [] 121 | if glif.find("outline") is not None: 122 | for contour in glif.find("outline"): 123 | if contour.tag == "contour": 124 | c = [] 125 | for p in contour: 126 | x = num(p.get("x")) 127 | y = num(p.get("y")) 128 | type = p.get("type") 129 | if type is None: 130 | type = "offcurve" 131 | smooth = p.get("smooth") == "yes" 132 | c.append(Point(x, y, type, smooth)) 133 | contours.append(c) 134 | anchors = [] 135 | for a in glif: 136 | if a.tag == "anchor": 137 | x = int(a.get("x")) 138 | y = int(a.get("y")) 139 | anchor_name = a.get("name") 140 | anchors.append(Anchor(x, y, anchor_name)) 141 | g = Glif(name, unicode_hex, w, contours, anchors) 142 | verify(g) 143 | return g 144 | 145 | def parse_points(x, scale, height): 146 | points = [] 147 | for p in x: 148 | if p.find(",") != -1: 149 | x, y = p.split(",") 150 | points.append([ 151 | (float(x)*scale), 152 | ((height-float(y))*scale) 153 | ]) 154 | else: 155 | break 156 | return points 157 | 158 | def parse_svg(svg_str: str) -> Glif: 159 | #scale = 1/18 * 1000 160 | scale = 1.0 161 | svg = fromstring(svg_str) 162 | # FIXME: 163 | name = "a" 164 | width = float(svg.get("width")) 165 | height = float(svg.get("height")) 166 | w = round(width * scale) 167 | h = round(height * scale) 168 | unicode_hex = None 169 | 170 | contours = [] 171 | path = svg[2] 172 | if path.get("id") != "path0": 173 | print("Path ID differs:", path.get("id")) 174 | p = path.get("d") 175 | x = p.split() 176 | 177 | i = 0 178 | contour = [] 179 | current_x = 0 180 | current_y = h 181 | while True: 182 | if i >= len(x): 183 | break 184 | if x[i] == "m": 185 | points = parse_points(x[i+1:], scale, 0) 186 | p = points[0] 187 | current_x += p[0] 188 | current_y += p[1] 189 | contour.append(Point( 190 | x=current_x, 191 | y=current_y, 192 | type="move", smooth=False)) 193 | for p in points[1:]: 194 | contour.append(Point( 195 | x=current_x+p[0], 196 | y=current_y+p[1], 197 | type="line", smooth=False)) 198 | current_x = contour[-1].x 199 | current_y = contour[-1].y 200 | i += len(points) + 1 201 | elif x[i] == "M": 202 | points = parse_points(x[i+1:], scale, height) 203 | p = points[0] 204 | current_x = p[0] 205 | current_y = p[1] 206 | contour.append(Point( 207 | x=current_x, 208 | y=current_y, 209 | type="move", smooth=False)) 210 | for p in points[1:]: 211 | contour.append(Point( 212 | x=p[0], 213 | y=p[1], 214 | type="line", smooth=False)) 215 | current_x = contour[-1].x 216 | current_y = contour[-1].y 217 | i += len(points) + 1 218 | elif x[i] == "c": 219 | points = parse_points(x[i+1:], scale, 0) 220 | assert len(points) % 3 == 0 221 | for j in range(len(points) // 3): 222 | contour.append(Point( 223 | x=current_x+points[3*j][0], 224 | y=current_y+points[3*j][1], 225 | type="offcurve", smooth=False)) 226 | contour.append(Point( 227 | x=current_x+points[3*j+1][0], 228 | y=current_y+points[3*j+1][1], 229 | type="offcurve", smooth=False)) 230 | contour.append(Point( 231 | x=current_x+points[3*j+2][0], 232 | y=current_y+points[3*j+2][1], 233 | type="curve", smooth=False)) 234 | current_x = contour[-1].x 235 | current_y = contour[-1].y 236 | i += len(points) + 1 237 | elif x[i] == "C": 238 | points = parse_points(x[i+1:], scale, height) 239 | assert len(points) % 3 == 0 240 | for j in range(len(points) // 3): 241 | contour.append(Point( 242 | x=points[3*j][0], 243 | y=points[3*j][1], 244 | type="offcurve", smooth=False)) 245 | contour.append(Point( 246 | x=points[3*j+1][0], 247 | y=points[3*j+1][1], 248 | type="offcurve", smooth=False)) 249 | contour.append(Point( 250 | x=points[3*j+2][0], 251 | y=points[3*j+2][1], 252 | type="curve", smooth=False)) 253 | current_x = contour[-1].x 254 | current_y = contour[-1].y 255 | i += len(points) + 1 256 | elif x[i] == "l": 257 | points = parse_points(x[i+1:], scale, 0) 258 | for p in points: 259 | contour.append(Point( 260 | x=current_x+p[0], 261 | y=current_y+p[1], 262 | type="line", smooth=False)) 263 | current_x = contour[-1].x 264 | current_y = contour[-1].y 265 | i += len(points) + 1 266 | elif x[i] == "L": 267 | points = parse_points(x[i+1:], scale, height) 268 | for p in points: 269 | contour.append(Point(x=p[0], y=p[1], type="line", smooth=False)) 270 | current_x = contour[-1].x 271 | current_y = contour[-1].y 272 | i += len(points) + 1 273 | elif x[i] == "h": 274 | points = [(float(x[i+1]))*scale] 275 | for p in points: 276 | contour.append(Point(x=current_x+p, y=current_y, type="line", smooth=False)) 277 | current_x = contour[-1].x 278 | current_y = contour[-1].y 279 | i += len(points) + 1 280 | elif x[i] == "H": 281 | points = [(float(x[i+1]))*scale] 282 | for p in points: 283 | contour.append(Point(x=p, y=current_y, type="line", smooth=False)) 284 | current_x = contour[-1].x 285 | current_y = contour[-1].y 286 | i += len(points) + 1 287 | elif x[i] == "v": 288 | points = [(-float(x[i+1]))*scale] 289 | for p in points: 290 | contour.append(Point(x=current_x, y=current_y+p, type="line", smooth=False)) 291 | current_x = contour[-1].x 292 | current_y = contour[-1].y 293 | i += len(points) + 1 294 | elif x[i] == "V": 295 | points = [(height-float(x[i+1]))*scale] 296 | for p in points: 297 | contour.append(Point(x=current_x, y=p, type="line", smooth=False)) 298 | current_x = contour[-1].x 299 | current_y = contour[-1].y 300 | i += len(points) + 1 301 | elif x[i] in ["A", "a"]: 302 | print(x[i]) 303 | raise Exception("Elliptical Arc Curve (A, a) not supported") 304 | elif x[i] in ["z", "Z"]: 305 | contour[0].type = "line" 306 | contours.append(contour) 307 | current_x = contour[0].x 308 | current_y = contour[0].y 309 | contour = [] 310 | i += 1 311 | else: 312 | print(x[i]) 313 | raise Exception("Not supported") 314 | 315 | anchors = [] 316 | g = Glif(name, unicode_hex, w, contours, anchors) 317 | verify(g) 318 | return g 319 | 320 | # Glif -> SVG: 321 | 322 | def glif2svg(glif: Glif, separate_paths: bool, fill: bool, 323 | stroke_width: int) -> str: 324 | h = 800 325 | svg = Element('svg', width=str(glif.w), height=str(h), version='1.1', 326 | xmlns='http://www.w3.org/2000/svg') 327 | 328 | path_str = "" 329 | 330 | for n, contour in enumerate(glif.contours): 331 | p0 = contour[0] 332 | assert p0.type != "offcurve" 333 | assert p0.type in ["curve", "line", "move"] 334 | is_curve = (contour[1].type in ["offcurve", "curve"]) 335 | if is_curve: 336 | path_str += "M {},{} C".format(p0.x, h-p0.y) 337 | else: 338 | path_str += "M {},{} L".format(p0.x, h-p0.y) 339 | if p0.type != "move": 340 | contour = contour + [p0] 341 | for point in contour[1:]: 342 | if point.type in ["offcurve", "curve"]: 343 | if is_curve: 344 | path_str += " {},{}".format(point.x, h-point.y) 345 | else: 346 | is_curve = True 347 | path_str += " C {},{}".format(point.x, h-point.y) 348 | else: 349 | assert point.type == "line" 350 | if is_curve: 351 | is_curve = False 352 | path_str += " L {},{}".format(point.x, h-point.y) 353 | else: 354 | path_str += " {},{}".format(point.x, h-point.y) 355 | if p0.type != "move": 356 | path_str += " Z" 357 | if separate_paths: 358 | p = Element('path', d=path_str, fill='none', stroke="black", 359 | style="stroke-linecap:butt;stroke-linejoin:mitter", 360 | id=f"path{n}", 361 | attrib={"stroke-width": str(stroke_width)}) 362 | svg.append(p) 363 | path_str = "" 364 | else: 365 | path_str += " " 366 | if not separate_paths: 367 | if fill: 368 | p = Element('path', d=path_str, fill="black", stroke="black", 369 | style="stroke-linecap:butt;stroke-linejoin:round", 370 | id="path0", 371 | attrib={"stroke-width": "0.0"}) 372 | else: 373 | p = Element('path', d=path_str, fill="none", stroke="black", 374 | style="stroke-linecap:butt;stroke-linejoin:mitter", 375 | id="path0", 376 | attrib={"stroke-width": str(stroke_width)}) 377 | svg.append(p) 378 | 379 | for anchor in glif.anchors: 380 | p = Element('circle', cx=str(anchor.x), cy=str(h-anchor.y), 381 | stroke="black", r="10", id=f"{anchor.name}", 382 | attrib={"stroke-width": "2.0"}) 383 | svg.append(p) 384 | 385 | svg_out = '\n' 386 | indent(svg, space=" ") 387 | svg_out += tostring(svg).decode() + "\n" 388 | return svg_out 389 | 390 | # Glif -> Glif: 391 | 392 | def glif2glif(glif: Glif) -> str: 393 | attrib = {} 394 | svg = Element('glyph', name=glif.name, format="2") 395 | 396 | advance = Element("advance", width=str(glif.w)) 397 | svg.append(advance) 398 | 399 | if len(glif.contours) > 0: 400 | outline = Element('outline') 401 | for contour in glif.contours: 402 | contour_ = Element("contour") 403 | for point in contour: 404 | attrib = {} 405 | if point.smooth: 406 | attrib["smooth"] = "yes" 407 | if point.type != "offcurve": 408 | attrib["type"] = point.type 409 | point_ = Element("point", x=str(point.x), y=str(point.y), 410 | attrib=attrib) 411 | contour_.append(point_) 412 | outline.append(contour_) 413 | svg.append(outline) 414 | 415 | # for anchor in glif.anchors: 416 | # p = Element('circle', cx=str(anchor.x), cy=str(h-anchor.y), 417 | # stroke="black", r="10", id=f"{anchor.name}", 418 | # attrib={"stroke-width": "2.0"}) 419 | # svg.append(p) 420 | 421 | svg_out = '\n' 422 | indent(svg, space=" ") 423 | svg_out += tostring(svg).decode() + "\n" 424 | return svg_out 425 | -------------------------------------------------------------------------------- /font.ufo/features.fea: -------------------------------------------------------------------------------- 1 | # # Documentation 2 | # 3 | # This file's syntax and semantics is documented at: 4 | # 5 | # http://adobe-type-tools.github.io/afdko/OpenTypeFeatureFileSpecification.html 6 | # 7 | # The asdfo library then compiles it to an OTF font, the glyph substitution 8 | # part creates GSUB tables in the OTF font. The general documentation how the 9 | # Glyph Substitution table (GSUB) works is described at: 10 | # 11 | # https://docs.microsoft.com/en-us/typography/opentype/spec/gsub 12 | # 13 | # Roughly speaking, the GSUB mechanism is composed of substitution lookups 14 | # (LookupList) tables, each is one of 7 kinds: 15 | # * GSUB LookupType 1: single (a -> x) 16 | # * GSUB LookupType 2: multiple (a -> x y z) 17 | # * GSUB LookupType 3: alternate (a -> x, where x is one of several glyphs) 18 | # * GSUB LookupType 4: ligature (a b c -> x) 19 | # * GSUB LookupType 5: context (a b' d -> x) 20 | # * GSUB LookupType 6: chaining context (chain multiple "context" substitutions) 21 | # * GSUB LookupType 7: extension (use 32-bit offsets instead of 16-bit) 22 | # * GSUB LookupType 8: reverse chaining context (applied from right to left) 23 | # 24 | # The `features.fea` file compiles into these tables, but allows to specify the 25 | # rules in a higher level / simpler language. 26 | # 27 | # # Single 28 | # 29 | # substitute by ; # format A 30 | # substitute by ; # format B 31 | # substitute by ; # format C 32 | # 33 | # E.g.: 34 | # 35 | # substitute a by A.sc; 36 | # 37 | # # Multiple 38 | # 39 | # substitute by ; 40 | # 41 | # E.g.: 42 | # 43 | # substitute f_f_i by f f i; 44 | # sub ka by ka.pas_cakra ka; 45 | # 46 | # # Alternate 47 | # 48 | # substitute from ; 49 | # 50 | # E.g.: 51 | # 52 | # substitute ampersand from [ampersand.1 ampersand.2 ampersand.3]; 53 | # 54 | # # Ligature 55 | # 56 | # substitute by ; 57 | # 58 | # E.g.: 59 | # 60 | # sub f i by f_i; 61 | # sub f f i by f_f_i; 62 | # sub ka ka.pas_cakra.ns by ka; 63 | # 64 | # The order does not matter, the rendering engine sorts from longest to 65 | # shortest. 66 | # 67 | # # Context 68 | # 69 | # E.g.: 70 | # 71 | # substitute a b c' d' e f by x y 72 | # substitute c' by x y 73 | # 74 | # The rule has three parts: backtrack (a b), input (c' d'), 75 | # and lookahead (e f) glyph sequences. The input is required, 76 | # backtrack/lookahead is optional. 77 | # 78 | # The order matters, the first takes priority. 79 | # 80 | # 81 | # # Chaining Context 82 | # 83 | # E.g.: 84 | # 85 | # sub ka' lookup REMOVE_CAKRA lookup REORDER_CAKRA ka.pas_cakra.ns' ; 86 | # substitute [ a e i o u] f' lookup CNTXT_LIGS i' n' lookup CNTXT_SUB; 87 | # 88 | # The order matters, the first takes priority. 89 | # 90 | # The lookup can only be called for "input" part, and the lookup substitution 91 | # is applied for each position (so CNTXT_LIGS for f' and CNTXT_SUB for n'). 92 | # 93 | # Within each lookup, either exactly one rule will apply (and the new sequence 94 | # is passed to the next lookup) or no rule will apply (and the original 95 | # sequence is passed). 96 | # 97 | # The rule is first matched, for example `ka' ka.pas_cakra.ns'` or 98 | # `[ a e i o u] f' i' n'`, and if it matches, then the lookup subsitutions are 99 | # performed in order from left to right at the given position. 100 | # 101 | # Worked out example: 102 | # 103 | # lookup CNTXT_LIGS { 104 | # substitute f i by f_i; 105 | # substitute c t by c_t; 106 | # } CNTXT_LIGS; 107 | # 108 | # lookup CNTXT_SUB { 109 | # substitute n by n.end; 110 | # substitute s by s.end; 111 | # } CNTXT_SUB; 112 | # 113 | # feature test { 114 | # substitute [ a e i o u] f' lookup CNTXT_LIGS i' n' lookup CNTXT_SUB; 115 | # substitute [ a e i o u] c' lookup CNTXT_LIGS t' s' lookup CNTXT_SUB; 116 | # } test; 117 | # 118 | # Here are the steps: 119 | # 120 | # a f i n -> a f_i n -> a f_i n.end 121 | # e c t s -> a c_t s -> a c_t s.end 122 | # e c t n -> e c t n # no match 123 | # 124 | # 125 | 126 | languagesystem DFLT dflt; 127 | languagesystem latn dflt; 128 | 129 | # Basic letters from unicode input (no connections, no begin/end) 130 | @LETTER_LC = [a-z 131 | aacute adieresis ccaron dcaron eacute ecaron iacute lacute lcaron ncaron 132 | oacute ocircumflex racute rcaron scaron tcaron uacute uring yacute zcaron]; 133 | 134 | @LETTER_UC = [A-Z 135 | Aacute Adieresis Ccaron Dcaron Eacute Ecaron Iacute Lacute Lcaron Ncaron 136 | Oacute Ocircumflex Racute Rcaron Scaron Tcaron Uacute Uring Yacute Zcaron]; 137 | 138 | @LETTER0 = [@LETTER_LC @LETTER_UC]; 139 | 140 | # Our custom versions of letters, cannot be input directly 141 | @LETTER1 = [sleft sdepth scaronleft scarondepth bnarrow onarrow oacutenarrow ocircumflexnarrow vnarrow wnarrow]; 142 | 143 | # All inner word connections (no begin/end), cannot be input directly 144 | @CONN = [conn_s conn_sv conn_P]; 145 | 146 | # All letters including connecting paths (conn_s, conn_sv, ...), but no begin 147 | # and end glyphs 148 | @LETTER = [@LETTER0 @LETTER1 @CONN]; 149 | 150 | @BCONN_LETTERS = [m n ncaron v w y yacute]; 151 | @SCONN_LETTERS = [@BCONN_LETTERS t tcaron z zcaron]; 152 | 153 | # All lower case letters and variations and internal connections 154 | @LCLETTERS = [@LETTER_LC @LETTER1 @CONN]; 155 | 156 | 157 | lookup LETTER_BEGIN { 158 | # beginning of the word 159 | ignore substitute @LETTER b'; 160 | substitute b' by begin b; 161 | ignore substitute @LETTER e'; 162 | substitute e' by begin e; 163 | ignore substitute @LETTER eacute'; 164 | substitute eacute' by begin eacute; 165 | ignore substitute @LETTER ecaron'; 166 | substitute ecaron' by begin ecaron; 167 | ignore substitute @LETTER f'; 168 | substitute f' by begin f; 169 | ignore substitute @LETTER h'; 170 | substitute h' by begin h; 171 | ignore substitute @LETTER i'; 172 | substitute i' by begin i; 173 | ignore substitute @LETTER iacute'; 174 | substitute iacute' by begin iacute; 175 | ignore substitute @LETTER j'; 176 | substitute j' by begin j; 177 | ignore substitute @LETTER k'; 178 | substitute k' by begin k; 179 | ignore substitute @LETTER l'; 180 | substitute l' by begin l; 181 | ignore substitute @LETTER lacute'; 182 | substitute lacute' by begin lacute; 183 | ignore substitute @LETTER lcaron'; 184 | substitute lcaron' by begin lcaron; 185 | ignore substitute @LETTER m'; 186 | substitute m' by begin_straight m; 187 | ignore substitute @LETTER n'; 188 | substitute n' by begin_straight n; 189 | ignore substitute @LETTER ncaron'; 190 | substitute ncaron' by begin_straight ncaron; 191 | ignore substitute @LETTER p'; 192 | substitute p' by begin p; 193 | ignore substitute @LETTER r'; 194 | substitute r' by begin r; 195 | ignore substitute @LETTER rcaron'; 196 | substitute rcaron' by begin rcaron; 197 | ignore substitute @LETTER racute'; 198 | substitute racute' by begin racute; 199 | ignore substitute @LETTER s'; 200 | substitute s' by begin s; 201 | ignore substitute @LETTER scaron'; 202 | substitute scaron' by begin scaron; 203 | ignore substitute @LETTER t'; 204 | substitute t' by begin t; 205 | ignore substitute @LETTER tcaron'; 206 | substitute tcaron' by begin tcaron; 207 | ignore substitute @LETTER u'; 208 | substitute u' by begin u; 209 | ignore substitute @LETTER uacute'; 210 | substitute uacute' by begin uacute; 211 | ignore substitute @LETTER uring'; 212 | substitute uring' by begin uring; 213 | ignore substitute @LETTER v'; 214 | substitute v' by begin_straight v; 215 | ignore substitute @LETTER w'; 216 | substitute w' by begin_straight w; 217 | ignore substitute @LETTER x'; 218 | substitute x' by begin_x x; 219 | ignore substitute @LETTER y'; 220 | substitute y' by begin_straight y; 221 | ignore substitute @LETTER yacute'; 222 | substitute yacute' by begin_straight yacute; 223 | ignore substitute @LETTER z'; 224 | substitute z' by begin_straight z; 225 | ignore substitute @LETTER zcaron'; 226 | substitute zcaron' by begin_straight zcaron; 227 | } LETTER_BEGIN; 228 | 229 | lookup LETTER_END { 230 | # end of the word 231 | ignore substitute a' @LETTER; 232 | substitute a' by a end; 233 | ignore substitute aacute' @LETTER; 234 | substitute aacute' by aacute end; 235 | ignore substitute adieresis' @LETTER; 236 | substitute adieresis' by adieresis end; 237 | ignore substitute b' @LETTER; 238 | substitute b' by b end; 239 | ignore substitute c' @LETTER; 240 | substitute c' by c end; 241 | ignore substitute ccaron' @LETTER; 242 | substitute ccaron' by ccaron end; 243 | ignore substitute d' @LETTER; 244 | substitute d' by d end; 245 | ignore substitute dcaron' @LETTER; 246 | substitute dcaron' by dcaron end; 247 | ignore substitute e' @LETTER; 248 | substitute e' by e end; 249 | ignore substitute eacute' @LETTER; 250 | substitute eacute' by eacute end; 251 | ignore substitute ecaron' @LETTER; 252 | substitute ecaron' by ecaron end; 253 | ignore substitute f' @LETTER; 254 | substitute f' by f end; 255 | ignore substitute g' @LETTER; 256 | substitute g' by g end; 257 | ignore substitute h' @LETTER; 258 | substitute h' by h end; 259 | ignore substitute i' @LETTER; 260 | substitute i' by i end; 261 | ignore substitute iacute' @LETTER; 262 | substitute iacute' by iacute end; 263 | ignore substitute j' @LETTER; 264 | substitute j' by j end; 265 | ignore substitute k' @LETTER; 266 | substitute k' by k end; 267 | ignore substitute l' @LETTER; 268 | substitute l' by l end; 269 | ignore substitute lacute' @LETTER; 270 | substitute lacute' by lacute end; 271 | ignore substitute lcaron' @LETTER; 272 | substitute lcaron' by lcaron end; 273 | ignore substitute m' @LETTER; 274 | substitute m' by m end; 275 | ignore substitute n' @LETTER; 276 | substitute n' by n end; 277 | ignore substitute ncaron' @LETTER; 278 | substitute ncaron' by ncaron end; 279 | ignore substitute o' @LETTER; 280 | substitute o' by o end; 281 | ignore substitute oacute' @LETTER; 282 | substitute oacute' by oacute end; 283 | ignore substitute ocircumflex' @LETTER; 284 | substitute ocircumflex' by ocircumflex end; 285 | ignore substitute p' @LETTER; 286 | substitute p' by p end; 287 | ignore substitute q' @LETTER; 288 | substitute q' by q end; 289 | ignore substitute r' @LETTER; 290 | substitute r' by r end; 291 | ignore substitute racute' @LETTER; 292 | substitute racute' by racute end; 293 | ignore substitute rcaron' @LETTER; 294 | substitute rcaron' by rcaron end; 295 | ignore substitute t' @LETTER; 296 | substitute t' by t end; 297 | ignore substitute tcaron' @LETTER; 298 | substitute tcaron' by tcaron end; 299 | ignore substitute u' @LETTER; 300 | substitute u' by u end; 301 | ignore substitute uacute' @LETTER; 302 | substitute uacute' by uacute end; 303 | ignore substitute uring' @LETTER; 304 | substitute uring' by uring end; 305 | ignore substitute v' @LETTER; 306 | substitute v' by v end; 307 | ignore substitute w' @LETTER; 308 | substitute w' by w end; 309 | ignore substitute x' @LETTER; 310 | substitute x' by x end; 311 | ignore substitute y' @LETTER; 312 | substitute y' by y end; 313 | ignore substitute yacute' @LETTER; 314 | substitute yacute' by yacute end; 315 | ignore substitute z' @LETTER; 316 | substitute z' by z end; 317 | ignore substitute zcaron' @LETTER; 318 | substitute zcaron' by zcaron end; 319 | 320 | ignore substitute A' @LETTER; 321 | substitute A' by A end; 322 | ignore substitute Aacute' @LETTER; 323 | substitute Aacute' by Aacute end; 324 | ignore substitute Adieresis' @LETTER; 325 | substitute Adieresis' by Adieresis end; 326 | ignore substitute C' @LETTER; 327 | substitute C' by C end; 328 | ignore substitute Ccaron' @LETTER; 329 | substitute Ccaron' by Ccaron end; 330 | ignore substitute E' @LETTER; 331 | substitute E' by E end; 332 | ignore substitute Eacute' @LETTER; 333 | substitute Eacute' by Eacute end; 334 | ignore substitute Ecaron' @LETTER; 335 | substitute Ecaron' by Ecaron end; 336 | ignore substitute G' @LETTER; 337 | substitute G' by G end; 338 | ignore substitute H' @LETTER; 339 | substitute H' by H end; 340 | ignore substitute J' @LETTER; 341 | substitute J' by J end; 342 | ignore substitute K' @LETTER; 343 | substitute K' by K end; 344 | ignore substitute L' @LETTER; 345 | substitute L' by L end; 346 | ignore substitute Lacute' @LETTER; 347 | substitute Lacute' by Lacute end; 348 | ignore substitute Lcaron' @LETTER; 349 | substitute Lcaron' by Lcaron end; 350 | ignore substitute M' @LETTER; 351 | substitute M' by M end; 352 | ignore substitute N' @LETTER; 353 | substitute N' by N end; 354 | ignore substitute Q' @LETTER; 355 | substitute Q' by Q end; 356 | ignore substitute Ncaron' @LETTER; 357 | substitute Ncaron' by Ncaron end; 358 | ignore substitute R' @LETTER; 359 | substitute R' by R end; 360 | ignore substitute Racute' @LETTER; 361 | substitute Racute' by Racute end; 362 | ignore substitute Rcaron' @LETTER; 363 | substitute Rcaron' by Rcaron end; 364 | ignore substitute U' @LETTER; 365 | substitute U' by U end; 366 | ignore substitute Uacute' @LETTER; 367 | substitute Uacute' by Uacute end; 368 | ignore substitute Uring' @LETTER; 369 | substitute Uring' by Uring end; 370 | ignore substitute Y' @LETTER; 371 | substitute Y' by Y end; 372 | ignore substitute Yacute' @LETTER; 373 | substitute Yacute' by Yacute end; 374 | ignore substitute Z' @LETTER; 375 | substitute Z' by Z end; 376 | ignore substitute Zcaron' @LETTER; 377 | substitute Zcaron' by Zcaron end; 378 | } LETTER_END; 379 | 380 | lookup SLEFT { 381 | ignore substitute @LETTER s'; 382 | substitute s' by sleft; 383 | ignore substitute @LETTER scaron'; 384 | substitute scaron' by scaronleft; 385 | } SLEFT; 386 | 387 | lookup SDEPTH { 388 | substitute [g j q y yacute Y Yacute] s' by sdepth; 389 | substitute [g j q y yacute Y Yacute] scaron' by scarondepth; 390 | } SDEPTH; 391 | 392 | lookup SCONN { 393 | substitute s' @SCONN_LETTERS by s conn_sv; 394 | substitute s' @LETTER by s conn_s; 395 | substitute scaron' @SCONN_LETTERS by scaron conn_sv; 396 | substitute scaron' @LETTER by scaron conn_s; 397 | substitute sleft' @SCONN_LETTERS by sleft conn_sv; 398 | substitute sleft' @LETTER by sleft conn_s; 399 | substitute sdepth' @SCONN_LETTERS by sdepth conn_sv; 400 | substitute sdepth' @LETTER by sdepth conn_s; 401 | substitute scaronleft' @SCONN_LETTERS by scaronleft conn_sv; 402 | substitute scaronleft' @LETTER by scaronleft conn_s; 403 | substitute scarondepth' @SCONN_LETTERS by scarondepth conn_sv; 404 | substitute scarondepth' @LETTER by scarondepth conn_s; 405 | } SCONN; 406 | 407 | lookup BCONN { 408 | substitute b' @BCONN_LETTERS by bnarrow; 409 | substitute begin' b' @BCONN_LETTERS by subs_token; 410 | } BCONN; 411 | lookup BCONN2 { 412 | substitute subs_token by begin bnarrow; 413 | } BCONN2; 414 | 415 | lookup OCONN { 416 | substitute o' @BCONN_LETTERS by onarrow; 417 | substitute oacute' @BCONN_LETTERS by oacutenarrow; 418 | substitute ocircumflex' @BCONN_LETTERS by ocircumflexnarrow; 419 | } OCONN; 420 | 421 | lookup VCONN { 422 | substitute v' @BCONN_LETTERS by vnarrow; 423 | substitute begin_straight' v' @BCONN_LETTERS by subs_token; 424 | } VCONN; 425 | lookup VCONN2 { 426 | substitute subs_token by begin_straight vnarrow; 427 | } VCONN2; 428 | 429 | lookup WCONN { 430 | substitute w' @BCONN_LETTERS by wnarrow; 431 | substitute begin_straight' w' @BCONN_LETTERS by subs_token; 432 | } WCONN; 433 | lookup WCONN2 { 434 | substitute subs_token by begin_straight wnarrow; 435 | } WCONN2; 436 | 437 | lookup BUCCONN { 438 | substitute B' @LETTER_LC by B conn_s; 439 | substitute D' @LETTER_LC by D conn_s; 440 | substitute Dcaron' @LETTER_LC by Dcaron conn_s; 441 | substitute F' @LETTER_LC by F conn_s; 442 | substitute I' @LETTER_LC by I conn_s; 443 | substitute Iacute' @LETTER_LC by Iacute conn_s; 444 | substitute O' @LETTER_LC by O conn_s; 445 | substitute Oacute' @LETTER_LC by Oacute conn_s; 446 | substitute Ocircumflex' @LETTER_LC by Ocircumflex conn_s; 447 | substitute S' @LETTER_LC by S conn_s; 448 | substitute Scaron' @LETTER_LC by Scaron conn_s; 449 | substitute T' @LETTER_LC by T conn_s; 450 | substitute Tcaron' @LETTER_LC by Tcaron conn_s; 451 | substitute V' @LETTER_LC by V conn_s; 452 | substitute W' @LETTER_LC by W conn_s; 453 | } BUCCONN; 454 | 455 | lookup PCONN { 456 | substitute P' @LETTER_LC by P conn_P; 457 | } PCONN; 458 | 459 | # the kern is 2u, where u=40 (using our scale=40), so total 80 460 | feature kern { 461 | ignore position @LETTER a'; 462 | position a' <80 0 80 0>; 463 | ignore position @LETTER aacute'; 464 | position aacute' <80 0 80 0>; 465 | ignore position @LETTER adieresis'; 466 | position adieresis' <80 0 80 0>; 467 | ignore position @LETTER c'; 468 | position c' <80 0 80 0>; 469 | ignore position @LETTER ccaron'; 470 | position ccaron' <80 0 80 0>; 471 | ignore position @LETTER d'; 472 | position d' <80 0 80 0>; 473 | ignore position @LETTER dcaron'; 474 | position dcaron' <80 0 80 0>; 475 | ignore position @LETTER g'; 476 | position g' <80 0 80 0>; 477 | ignore position @LETTER o'; 478 | position o' <80 0 80 0>; 479 | ignore position @LETTER oacute'; 480 | position oacute' <80 0 80 0>; 481 | ignore position @LETTER ocircumflex'; 482 | position ocircumflex' <80 0 80 0>; 483 | ignore position @LETTER onarrow'; 484 | position onarrow' <80 0 80 0>; 485 | ignore position @LETTER oacutenarrow'; 486 | position oacutenarrow' <80 0 80 0>; 487 | ignore position @LETTER ocircumflexnarrow'; 488 | position ocircumflexnarrow' <80 0 80 0>; 489 | ignore position @LETTER q'; 490 | position q' <80 0 80 0>; 491 | 492 | ignore position B' @LCLETTERS; 493 | position B' <0 0 80 0>; 494 | ignore position D' @LCLETTERS; 495 | position D' <0 0 80 0>; 496 | ignore position Dcaron' @LCLETTERS; 497 | position Dcaron' <0 0 80 0>; 498 | ignore position F' @LCLETTERS; 499 | position F' <0 0 240 0>; 500 | ignore position I' @LCLETTERS; 501 | position I' <0 0 40 0>; 502 | ignore position Iacute' @LCLETTERS; 503 | position Iacute' <0 0 40 0>; 504 | ignore position O' @LCLETTERS; 505 | position O' <0 0 160 0>; 506 | ignore position Oacute' @LCLETTERS; 507 | position Oacute' <0 0 160 0>; 508 | ignore position Ocircumflex' @LCLETTERS; 509 | position Ocircumflex' <0 0 160 0>; 510 | ignore position P' @LCLETTERS; 511 | position P' <0 0 280 0>; 512 | ignore position S' @LCLETTERS; 513 | position S' <0 0 160 0>; 514 | ignore position Scaron' @LCLETTERS; 515 | position Scaron' <0 0 160 0>; 516 | ignore position T' @LCLETTERS; 517 | position T' <0 0 280 0>; 518 | ignore position Tcaron' @LCLETTERS; 519 | position Tcaron' <0 0 280 0>; 520 | ignore position V' @LCLETTERS; 521 | position V' <0 0 240 0>; 522 | ignore position W' @LCLETTERS; 523 | position W' <0 0 240 0>; 524 | } kern; 525 | 526 | feature liga { 527 | substitute s' lookup SLEFT lookup SDEPTH lookup SCONN; 528 | substitute scaron' lookup SLEFT lookup SDEPTH lookup SCONN; 529 | substitute b' lookup LETTER_END lookup LETTER_BEGIN lookup BCONN lookup BCONN2; 530 | substitute o' lookup LETTER_END lookup OCONN; 531 | substitute oacute' lookup LETTER_END lookup OCONN; 532 | substitute ocircumflex' lookup LETTER_END lookup OCONN; 533 | substitute v' lookup LETTER_END lookup LETTER_BEGIN lookup VCONN lookup VCONN2; 534 | substitute w' lookup LETTER_END lookup LETTER_BEGIN lookup WCONN lookup WCONN2; 535 | substitute [B D Dcaron F I Iacute O Oacute Ocircumflex S Scaron 536 | T Tcaron V W]' lookup BUCCONN; 537 | substitute P' lookup PCONN; 538 | substitute @LETTER0' lookup LETTER_END lookup LETTER_BEGIN; 539 | } liga; 540 | -------------------------------------------------------------------------------- /gen/svg.py: -------------------------------------------------------------------------------- 1 | """ 2 | This file creates SVG files for each glyph in the font specified using the 3 | Metafont approach. 4 | 5 | The actual shapes are taken from the Slabikář font by Petr Olšák, and the 6 | original metafont source code is copied here for each glyph as a comment for 7 | reference. 8 | 9 | The metafont path is represented by nodes, optional tangents and tensions. From 10 | this information one can obtain bezier control points. We implemented the 11 | tangent+tension -> bezier control points calculation exactly. We currently 12 | require all tangents to be specified explicitly. The original Metafont source 13 | has some implicit tangents, so we have estimated those by trial and error by 14 | hand. In the future we could implement the Metafont's algorithm for tangents as 15 | well. 16 | 17 | The generated SVG files contain the path of the cursive font. The files are 18 | then processed using Inkscape to produce outlines. We read them in, and convert 19 | to the UFO glif format, which is then used to construct the OTF font. 20 | 21 | 22 | 23 | # Documentation for SVG: 24 | # https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/d#path_commands 25 | # 26 | # One can check the generated svg document at: 27 | # https://validator.w3.org 28 | 29 | 30 | The otf design units are 1000x1000 pixels EM box. 31 | 32 | 72 pt = 1 inch 33 | 1 em = 11.95517 pt 34 | 35 | The metafont design units are 1pt = 0.083645em = 83.6458 px (pixels). 36 | 37 | It seems we have roughly 1pt = 40px. Why? 38 | """ 39 | 40 | # scale=70 lines up the lowercase letters with Source-Sans 41 | # scale=50 lines up the uppercase letters with Helvetica Neue and most other 42 | # fonts, so it is probably a better option to be consistent. 43 | # scale=40 agress with Metafont's Slabikar 44 | scale = 40 45 | stroke_width = 0.4 * scale 46 | 47 | # 1 .. original 48 | # 2 .. U.S. 49 | # 3 .. alternate "z" (for z_style only), like z_style=1, but with a loop 50 | # 4 .. alternate "z" (for z_style only), like "r", but with a loop 51 | z_style = 1 52 | t_style = 1 53 | 54 | 55 | import os 56 | from bezier import compute_control_points 57 | from math import sin, cos, pi 58 | from numpy import array 59 | from glif import Glif, verify, glif2svg, Point 60 | 61 | def shift(contour, s): 62 | p = [] 63 | for x in contour: 64 | p.append(Point(x=x.x+s[0], y=x.y+s[1], type=x.type, smooth=x.smooth)) 65 | return p 66 | 67 | #path = [z1, 68 | # [left, 1, z1p_tangent, z1p], 69 | # [z1p_tangent, 1, -sklon2, z0], 70 | # [-sklon2, 1.5, right, z2], 71 | # [right, 1.2, -sklon1, z1], 72 | # [sklon1, 1, sklon1, z3], 73 | # ] 74 | def _draw(path): 75 | contour = [ 76 | Point(x=path[0][0], y=path[0][1], type="move", smooth=False) 77 | ] 78 | for t1, tension, t2, z in path[1:]: 79 | if t1 is None: 80 | contour.append(Point(x=z[0], y=z[1], type="line", smooth=False)) 81 | else: 82 | z0 = [contour[-1].x, contour[-1].y] 83 | c1, c2 = compute_control_points(z0, z, t1, t2, tension) 84 | contour.extend([ 85 | Point(x=c1[0], y=c1[1], type="offcurve", smooth=False), 86 | Point(x=c2[0], y=c2[1], type="offcurve", smooth=False), 87 | Point(x=z[0], y=z[1], type="curve", smooth=False), 88 | ]) 89 | return contour 90 | 91 | #path = [(z1,left),1,(z1p,z1p_tangent),1,(z0,-sklon2),1.5, 92 | # (z2,right),1.2,(-sklon1,z1,sklon1),1,(z3,sklon1)] 93 | def _draw2(path): 94 | assert len(path) % 2 == 1 95 | p2 = [path[0][0]] 96 | for i in range((len(path)-1)//2): 97 | node1 = path[2*i]; tension = path[2*i+1]; node2 = path[2*i+2] 98 | if (len(node2) == 2): 99 | if tension is None: 100 | p2.append([None, None, None, node2[0]]) 101 | else: 102 | p2.append([node1[-1], tension, node2[1], node2[0]]) 103 | else: 104 | assert len(node2) == 3 105 | if tension is None: 106 | p2.append([None, None, None, node2[1]]) 107 | else: 108 | p2.append([node1[-1], tension, node2[0], node2[1]]) 109 | return _draw(p2) 110 | 111 | 112 | def create_glif(contours, w, scale): 113 | for contour in contours: 114 | for p in contour: 115 | p.x = float(p.x * scale) 116 | p.y = float(p.y * scale) 117 | w = float(w * scale) 118 | 119 | name = "a" 120 | unicode_hex = None 121 | anchors = [] 122 | g = Glif(name, unicode_hex, w, contours, anchors) 123 | verify(g) 124 | return g 125 | 126 | def add_char(charname, width, contours): 127 | g = create_glif(contours, width, scale) 128 | f = open(f'letter_{charname}.svg', 'w') 129 | f.write(glif2svg(g, False, False, stroke_width)) 130 | f.close() 131 | 132 | def whatever_y(z0, vec, zy): 133 | """ 134 | solves the equation z-z0=whatever*vec under the condition of z.y = zy 135 | """ 136 | w = (zy-z0[1]) / vec[1] 137 | zx = vec[0] * w + z0[0] 138 | z = [zx, zy] 139 | return z 140 | 141 | def dir_(angle_deg): 142 | a = angle_deg * pi/180 143 | return array([cos(a), sin(a)]) 144 | 145 | def run(cmd): 146 | print(cmd) 147 | r = os.system(cmd) 148 | if (r != 0): 149 | raise Exception("Command failed.") 150 | 151 | right=array([1,0]) 152 | left=array([-1,0]) 153 | down=array([0,-1]) 154 | up=array([0,1]) 155 | # add a curve: first point, and (control-point1, control-point2, node)*n points. 156 | # sklon1:=-(1.5,6); sklon2:=(5,6); 157 | sklon1=-array([1.5,6]); sklon2=array([5,6]); 158 | 159 | #def dotah = 160 | # draw ((0,1){sklon1}..(1,0){right}..{sklon2}(8,6)) 161 | #enddef; 162 | dotah = _draw2([((0,1),sklon1),1,((1,0),right),1,((8,6),sklon2)]) 163 | eps = stroke_width/2 / scale 164 | z1 = (eps,0); z2 = (0,eps); z3 = (-eps,0); z4=(0,-eps) 165 | dot = _draw2([(z1,up), 1, (z2,left), 1, (z3,down), 1, (z4, right), 1, 166 | (z1, up)]) 167 | 168 | #def smycka = 169 | # draw ((0,7){sklon1}..{sklon1}(-2,0)..{sklon1}(-3.1,-4).. 170 | # {left}(-5.3,-7)..{-sklon1}(-5.5,-5).. 171 | # (-2,0)..{sklon2}(5.5,6)) 172 | #enddef; 173 | smycka = _draw2([((0,7),sklon1),1,((-2,0),sklon1),1,((-3.1,-4),sklon1),1, 174 | ((-5.3,-7),left),1,((-5.5,-5),-sklon1),1, 175 | ((-2,0),(6,5)),1,((5.5,6),sklon2)]) 176 | 177 | carka = _draw2([((0,9),None),None,((1.5,13),None)]) 178 | capcarka = _draw2([((0,15),None),None,((1.5,18),None)]) 179 | #def krouzek = 180 | # draw ((0,9){right}..(0,11){left}..cycle) 181 | #enddef; 182 | eps = 1.0 183 | z1 = (eps,0); z2 = (0,eps); z3 = (-eps,0); z4=(0,-eps) 184 | krouzek = shift(_draw2([(z1,up), 1, (z2,left), 1, (z3,down), 1, (z4, right), 1, 185 | (z1, up)]), (0, 10)) 186 | vokan = _draw2([((0,9),(1,1)),1,((3,11),right),1,((4,9),dir_(-105))]) 187 | 188 | 189 | #def dvetecky (expr a, b) = 190 | # pickup pencircle scaled (dotkoef*thin); 191 | # drawdot (2 + a, 10 + b); 192 | # drawdot (4.4 + a, 10 + b); 193 | # pickup pencircle scaled thin 194 | #enddef; 195 | def dvetecky(x,y): 196 | #return [ 197 | # _draw2([((2+x-0.5,9+y),None),None,((2+1.5+x-0.5,12+y),None)]), 198 | # _draw2([((4.4+x-0.5,9+y),None),None,((4.4+1.5+x-0.5,12+y),None)]), 199 | #] 200 | return [ 201 | shift(dot, (2+x,10+y)), 202 | shift(dot, (4.4+x,10+y)), 203 | ] 204 | 205 | 206 | #def hacek = 207 | # draw ((0,12)..{sklon1}(-.3,10)..{right}(.8,9)..tension2..{sklon2}(5,12)) 208 | #enddef; 209 | # Note: (0.2,12) looks better 210 | hacek = _draw2([((0,12),sklon1),1,((-.3,10),sklon1),1,((.8,9),right),2,((5,12),sklon2)]) 211 | #def hacekl = 212 | # draw ((0,12)..{sklon1}(-.3,10)..{right}(.8,9)..tension2..{sklon2}(3.5,12)) 213 | #enddef; 214 | hacekl = _draw2([((0,12),sklon1),1,((-.3,10),sklon1),1,((.8,9),right),2,((3.5,12),sklon2)]) 215 | 216 | 217 | 218 | # Special characters 219 | 220 | # End of the character 221 | #beginchar(1, .7u#, 7u#, 0); %% pravy konec znaku 222 | # draw (0,6)..(.7,7); 223 | #endchar; 224 | # Original: 225 | # end_w = 0.7 226 | # New fix: 227 | end_w = sklon2[0]/sklon2[1] # =5/6=0.833... 228 | add_char("end", end_w, [ 229 | _draw2([((0,6),None), None, ((end_w,7),None)]), 230 | ]) 231 | 232 | # Beginning of the character 233 | #beginchar(2, 5u#, 7u#, 0); %% levy rovny zacatek znaku 234 | # draw (0,0)..(5,6); 235 | #endchar; 236 | add_char("begin_straight", 5, [ 237 | _draw2([((0,0),sklon2), 1, ((5,6),sklon2)]), 238 | ]) 239 | 240 | #beginchar(3, 6u#, 7u#, 0); %% levy prohnuty zacatek znaku 241 | # draw (0,0){(3,2)}..{sklon2}(6,6); 242 | #endchar; 243 | add_char("begin", 6, [ 244 | _draw2([((0,0),(3,2)), 1, ((6,6),sklon2)]), 245 | ]) 246 | 247 | #beginchar(4, 5u#, 7u#, 0); %% obecna konvexni spojka za verzalkou a s 248 | # draw (-4,0){right}..{sklon2}(5,6); 249 | #endchar; 250 | add_char("conn_s", 5, [ 251 | _draw2([((-4,0),right), 1, ((5,6),sklon2)]), 252 | ]) 253 | 254 | #beginchar(5, 7u#, 7u#, 0); %% delsi konvexni spojka za verzalkou P 255 | # draw (-4,0){right}..{sklon2}(7,6); 256 | #endchar; 257 | add_char("conn_P", 7, [ 258 | _draw2([((-4,0),right), 1, ((7,6),sklon2)]), 259 | ]) 260 | 261 | #beginchar(6, 3u#, 7u#, 0); %% kratsi konvexni spojka pro dvojice sv sn 262 | # draw (-4,0){right}..{sklon2}(3,6); 263 | #endchar; 264 | add_char("conn_sv", 3, [ 265 | _draw2([((-4,0),right), 1, ((3,6),sklon2)]), 266 | ]) 267 | 268 | #beginchar(7, 8u#, 7u#, 0); %% nabehova carka pro male x 269 | # draw (0,2){down}..(2,0){right}..tension2..{sklon2}(8,6); 270 | #endchar; 271 | add_char("begin_x", 8, [ 272 | _draw2([((0,2),down), 1, ((2,0),right), 2, ((8,6),sklon2)]), 273 | ]) 274 | 275 | 276 | ################################################################################ 277 | 278 | # Character definitions 279 | 280 | #beginchar("a", 9.4u#, 7u#, 0); 281 | # z0=(0,6); z1=(3,7); z2=(-1,0); z3=(1.4,1); 282 | # z1p=(1.5,6.9); 283 | # draw z1{left}..z1p..z0{-sklon2}..tension1.5.. 284 | # z2{right}..tension1.2..{-sklon1}z1{sklon1}..z3{sklon1}; 285 | # dotah shifted (x3,0); 286 | #endchar; 287 | z0=(0,6); z1=(3,7); z2=(-1,0); z3=(1.4,1); 288 | z1p=(1.5,6.9); z1p_tangent=(-4, -1) 289 | add_char("a", 9.4, [ 290 | _draw2([(z1,left),1,(z1p,z1p_tangent),1,(z0,-sklon2),1.5, 291 | (z2,right),1.2,(-sklon1,z1,sklon1),1,(z3,sklon1)]), 292 | shift(dotah, (z3[0],0)) 293 | ]) 294 | 295 | #beginchar(adiaeresis, 9.4u#, 7u#, 0); %% \"a 296 | # z0=(0,6); z1=(3,7); z2=(-1,0); z3=(1.4,1); 297 | # z1p=(1.5,6.9); 298 | # draw z1{left}..z1p..z0{-sklon2}..tension1.5.. 299 | # z2{right}..tension1.2..{-sklon1}z1{sklon1}..z3{sklon1}; 300 | # dotah shifted (x3,0); 301 | #% dvetecky (0,0); %%% Change 18. 5. 2020 to: 302 | # dvetecky (-0.5,0); 303 | #endchar; 304 | z0=(0,6); z1=(3,7); z2=(-1,0); z3=(1.4,1); 305 | z1p=(1.5,6.9); z1p_tangent=(-4, -1) 306 | add_char("adieresis", 9.4, [ 307 | _draw2([(z1,left),1,(z1p,z1p_tangent),1,(z0,-sklon2),1.5, 308 | (z2,right),1.2,(-sklon1,z1,sklon1),1,(z3,sklon1)]), 309 | shift(dotah, (z3[0],0))] + 310 | dvetecky(-0.5,0) 311 | ) 312 | 313 | #beginchar(aacute, 9.4u#, 13u#, 0); %% \'a 314 | # z0=(0,6); z1=(3,7); z2=(-1,0); z3=(1.4,1); 315 | # z1p=(1.5,6.9); 316 | # draw z1{left}..z1p..z0{-sklon2}..tension1.5.. 317 | # z2{right}..tension1.5..{-sklon1}z1{sklon1}..z3{sklon1}; 318 | # dotah shifted (x3,0); 319 | # carka shifted (3,0); 320 | #endchar; 321 | z0=(0,6); z1=(3,7); z2=(-1,0); z3=(1.4,1); 322 | z1p=(1.5,6.9); z1p_tangent=(-4, -1) 323 | # FIXME: the second tension is 1.5 in aacute in slabikar.mf, a bug 324 | add_char("aacute", 9.4, [ 325 | _draw2([(z1,left),1,(z1p,z1p_tangent),1,(z0,-sklon2),1.5, 326 | (z2,right),1.2,(-sklon1,z1,sklon1),1,(z3,sklon1)]), 327 | shift(dotah, (z3[0],0)), 328 | shift(carka, (3,0)) 329 | ]) 330 | 331 | 332 | #beginchar("b", 9u#, 14u#, 0); 333 | # z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1,1); 334 | # z4=(0,0); z5=(3,7); z6=(9,6); 335 | # z1p=(4,12); z5p=(2.5,6); 336 | # draw z0{sklon2}..z1p..tension1.5..z1{left}..z2{sklon1}.. 337 | # z3{sklon1}..z4{right}..tension3..z5{left}..z5p{down}.. 338 | # tension2..{sklon2}z6; 339 | #endchar; 340 | z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1,1); 341 | z4=(0,0); z5=(3,7); z6=(9,6); 342 | z1p=(4,12); z1p_tangent=(3,6); z5p=(2.5,6); 343 | add_char("b", 9, [ 344 | _draw2([(z0,sklon2),1,(z1p,z1p_tangent),1.5,(z1,left),1,(z2,sklon1),1, 345 | (z3,sklon1),1,(z4,right),3,(z5,left),1,(z5p,down), 346 | 2,(z6,sklon2)]), 347 | ]) 348 | 349 | #beginchar(bnarrow, 7u#, 14u#, 0); 350 | # z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1,1); 351 | # z4=(0,0); z5=(3,7); z6=(7,6); 352 | # z1p=(4,12); z5p=(2.5,6); 353 | # draw z0{sklon2}..z1p..tension1.5..z1{left}..z2{sklon1}.. 354 | # z3{sklon1}..z4{right}..tension3..z5{left}..z5p{down}.. 355 | # tension2..{sklon2}z6; 356 | #endchar; 357 | z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1,1); 358 | z4=(0,0); z5=(3,7); z6=(7,6); 359 | z1p=(4,12); z1p_tangent=(3,6); z5p=(2.5,6); 360 | add_char("bnarrow", 7, [ 361 | _draw2([(z0,sklon2),1,(z1p,z1p_tangent),1.5,(z1,left),1,(z2,sklon1),1, 362 | (z3,sklon1),1,(z4,right),3,(z5,left),1,(z5p,down), 363 | 2,(z6,sklon2)]), 364 | ]) 365 | 366 | 367 | #beginchar("c", 8u#, 7u#, 0); 368 | # z0=(0,6); z1=(1.5,7); z2=(2.5,6); z3=(0,0); z4=(8,6); 369 | # draw z2..z1{left}..z0{-sklon2}..z3{right}..{sklon2}z4; 370 | #endchar; 371 | z0=(0,6); z1=(1.5,7); z2=(2.5,6); z3=(0,0); z4=(8,6); z2t=(-4,1) 372 | add_char("c", 8, [ 373 | _draw2([(z2,up),1,(z1,left),1,(z0,-sklon2),1,(z3,right),1,(z4,sklon2)]) 374 | ]) 375 | 376 | #beginchar(ccaron, 8u#, 12u#, 0); 377 | # z0=(0,6); z1=(1.5,7); z2=(2.5,6); z3=(0,0); z4=(8,6); 378 | # draw z2..z1{left}..z0{-sklon2}..z3{right}..{sklon2}z4; 379 | # hacek shifted (2,0); 380 | #endchar; 381 | z0=(0,6); z1=(1.5,7); z2=(2.5,6); z3=(0,0); z4=(8,6); z2t=(-4,1) 382 | add_char("ccaron", 8, [ 383 | _draw2([(z2,up),1,(z1,left),1,(z0,-sklon2),1,(z3,right),1,(z4,sklon2)]), 384 | shift(hacek, (2,0)) 385 | ]) 386 | 387 | #beginchar("d", 9.4u#, 14u#, 0); 388 | # z0=(0,6); z1=(3,7); z2=(-1,0); z3=(1.4,1); 389 | # z1p=(1.5,6.9); 390 | # z1n-z3 = whatever * (z1-z3); y1n=14; 391 | # draw z1{left}..z1p..z0{-sklon2}..tension1.5.. 392 | # z2{right}..tension1.5..{-sklon1}z1--z1n{sklon1}..z3{sklon1}; 393 | # dotah shifted (x3,0); 394 | #endchar; 395 | z0=(0,6); z1=(3,7); z2=(-1,0); z3=(1.4,1); 396 | z1p=(1.5,6.9);z1pt=(-4,-1) # roughly: z0-z1, but adjusted 397 | z1n = whatever_y(z3, array(z1)-array(z3), 14) 398 | add_char("d", 9.4, [ 399 | _draw2([(z1,left),1,(z1p,z1pt),1,(z0,-sklon2),1.5, 400 | (z2,right),1.5,(z1,-sklon1),None,(z1n,sklon1),1,(z3,sklon1)]), 401 | shift(dotah, (z3[0],0)) 402 | ]) 403 | add_char("dcaron", 9.4, [ 404 | _draw2([(z1,left),1,(z1p,z1pt),1,(z0,-sklon2),1.5, 405 | (z2,right),1.5,(z1,-sklon1),None,(z1n,sklon1),1,(z3,sklon1)]), 406 | shift(dotah, (z3[0],0)), 407 | shift(hacek, (6,2)), 408 | ]) 409 | 410 | #beginchar("e", 5u#, 7u#, 0); 411 | # z0=(0,6); z1=(-1,7); z2=(-2,5); z3=(-3,1); 412 | # draw z0{sklon2}..z1{left}..z2{sklon1}..{sklon1}z3; 413 | # dotah shifted (x3,0); 414 | #endchar; 415 | z0=(0,6); z1=(-1,7); z2=(-2,5); z3=(-3,1); 416 | add_char("e", 5, [ 417 | _draw2([(z0,sklon2),1,(z1,left),1,(z2,sklon1),1,(z3,sklon1)]), 418 | shift(dotah, (z3[0],0)) 419 | ]) 420 | add_char("eacute", 5, [ 421 | _draw2([(z0,sklon2),1,(z1,left),1,(z2,sklon1),1,(z3,sklon1)]), 422 | shift(dotah, (z3[0],0)), 423 | shift(carka, (0,0)), 424 | ]) 425 | add_char("ecaron", 5, [ 426 | _draw2([(z0,sklon2),1,(z1,left),1,(z2,sklon1),1,(z3,sklon1)]), 427 | shift(dotah, (z3[0],0)), 428 | shift(hacek, (-0.5,0)), 429 | ]) 430 | 431 | #beginchar("f", 7u#, 14u#, 7u#); 432 | # z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1.2,0); 433 | # z1p=(4,12); 434 | # z3r=(-.8,0); z3l=(-1.6,.3); 435 | # z4=(-3,-6); z5=(-2.3,-7); z6=(7,6); 436 | # draw z0{sklon2}..z1p..tension1.5..z1{left}..z2{sklon1}..z3{sklon1} 437 | # ..z4{sklon1}..z5{right}..tension3.. 438 | # {(-2,1)}z3r..z3l{down}..z3r{right}..{sklon2}z6; 439 | #endchar; 440 | z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1.2,0); 441 | z1p=(4,12);z1p_t=(3,6) 442 | z3r=(-.8,0); z3l=(-1.6,.3); 443 | z4=(-3,-6); z5=(-2.3,-7); z6=(7,6); 444 | add_char("f", 7, [ 445 | _draw2([(z0,sklon2),1,(z1p,z1p_t),1.5,(z1,left),1,(z2,sklon1),1,(z3,sklon1), 446 | 1,(z4,sklon1),1,(z5,right),3,(z3r,(-2,1)),1,(z3l,down),1,(z3r,right),1, 447 | (z6,sklon2)]) 448 | ]) 449 | 450 | #beginchar("g", 8.5u#, 7u#, 7u#); 451 | # z0=(0,6); z1=(3,7); z2=(-1,0); z3=(1.4,1); 452 | # z1p=(1.5,6.9); 453 | # draw z1{left}..z1p..z0{-sklon2}..tension1.5.. 454 | # z2{right}..tension1.5..{-sklon1}z1; 455 | # smycka shifted (x1,0); 456 | #endchar; 457 | z0=(0,6); z1=(3,7); z2=(-1,0); z3=(1.4,1); 458 | z1p=(1.5,6.9);z1pt=(-4,-1) 459 | add_char("g", 8.5, [ 460 | _draw2([(z1,left),1,(z1p,z1pt),1,(z0,-sklon2),1.5, 461 | (z2,right),1.5,(z1,-sklon1)]), 462 | shift(smycka, (z1[0],0)) 463 | ]) 464 | 465 | #beginchar("h", 9.85u#, 14u#, 0); 466 | # z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1.2,0); 467 | # z1p=(4,12); 468 | # z4=(0.15,5); 469 | # z5n=(x4+2.5,7); z5=(x4+3,6); z6=(x4+1.7,1); 470 | # draw z0{sklon2}..z1p..tension1.5..z1{left}..z2{sklon1}..z3{sklon1}; 471 | # draw z4{-sklon1}..z5n{right}..z5{sklon1}..{sklon1}z6; 472 | # dotah shifted (x6,0); 473 | #endchar; 474 | z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1.2,0); 475 | z1p=(4,12);z1pt=(1,2) 476 | z4=(0.15,5); 477 | z5n=(z4[0]+2.5,7); z5=(z4[0]+3,6); z6=(z4[0]+1.7,1); 478 | add_char("h", 9.85, [ 479 | _draw2([(z0,sklon2),1,(z1p,z1pt),1.5,(z1,left),1,(z2,sklon1),1, 480 | (z3,sklon1)]), 481 | _draw2([(z4,-sklon1),1,(z5n,right),1,(z5,sklon1),1,(z6,sklon1)]), 482 | shift(dotah, (z6[0],0)) 483 | ]) 484 | 485 | #beginchar("i", 7u#, 11u#, 0); 486 | # z0=(0,6); z1=(.5,7); z2=(-1,1); z3-z1=whatever*sklon1; y3=11; 487 | # pickup pencircle scaled (dotkoef*thin); 488 | # drawdot z3; 489 | # pickup pencircle scaled thin; 490 | # draw z0{sklon2}..{-sklon1}z1{sklon1}..{sklon1}z2; 491 | # dotah shifted (x2,0); 492 | #endchar; 493 | z0=(0,6); z1=(.5,7); z2=(-1,1); z3 = whatever_y(z1, sklon1, 11) 494 | add_char("i", 7, [ 495 | _draw2([(z0,sklon2),1,(-sklon1,z1,sklon1),1,(z2,sklon1)]), 496 | shift(dot, z3), 497 | shift(dotah, (z2[0],0)) 498 | ]) 499 | z3 = whatever_y(z1, sklon1, 9) 500 | add_char("iacute", 7, [ 501 | _draw2([(z0,sklon2),1,(-sklon1,z1,sklon1),1,(z2,sklon1)]), 502 | shift(dotah, (z2[0],0)), 503 | shift(carka, (z3[0],0)) 504 | ]) 505 | 506 | #beginchar("j", 6u#, 11u#, 7u#); 507 | # z0=(0,6); z1=(.5,7); 508 | # z3-z1=whatever*sklon1; y3=11; 509 | # pickup pencircle scaled (dotkoef*thin); 510 | # drawdot z3; 511 | # pickup pencircle scaled thin; 512 | # draw z0{sklon2}..{-sklon1}z1; 513 | # smycka shifted (x1,0); 514 | #endchar; 515 | z0=(0,6); z1=(.5,7); z3 = whatever_y(z1, sklon1, 11) 516 | add_char("j", 6, [ 517 | _draw2([(z0,sklon2),1,(z1,-sklon1)]), 518 | shift(dot, z3), 519 | shift(smycka, (z1[0],0)) 520 | ]) 521 | 522 | #beginchar("k", 10u#, 14u#, 0); 523 | # z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1.2,0); 524 | # z1p=(4,12); 525 | # (z4-z3) = whatever*(z2-z3); y4=5; 526 | # z5=(2.3,7); z6=(2,4.5); z7=(1,y6); z8=(4,0); z9=(10,6); 527 | # draw z0{sklon2}..z1p..tension1.5..z1{left}..z2{sklon1}..z3{sklon1}; 528 | # draw z4{-sklon1}..z5{right}..z6..z7{up}..z6.. 529 | # z8{right}..tension3..{sklon2}z9; 530 | #endchar; 531 | z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1.2,0); 532 | z1p=(4,12);z1pt=(1,2) 533 | z4 = whatever_y(z3, array(z2)-array(z3), 5) 534 | z5=(2.3,7); z6=(2,4.5); z7=(1,z6[1]); z8=(4,0); z9=(10,6); 535 | z6t = (-1,-1) 536 | z6t2 = (1,-1) 537 | add_char("k", 10, [ 538 | _draw2([(z0,sklon2),1,(z1p,z1pt),1.5,(z1,left),1,(z2,sklon1),1,(z3,sklon1)]), 539 | _draw2([(z4,-sklon1),1,(z5,right),1,(z6,z6t),1,(z7,up),1,(z6,z6t2),1, 540 | (z8,right),3,(z9,sklon2)]), 541 | ]) 542 | 543 | 544 | #beginchar("l", 7u#, 14u#, 0); 545 | # z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1,1); 546 | # z1p=(4,12); 547 | # draw z0{sklon2}..z1p..tension1.5..z1{left}..z2{sklon1}..z3{sklon1}; 548 | # dotah shifted (x3,0); 549 | #endchar; 550 | z0=(0,6); z1=(4,14); z2=(1.5,10); z3=(-1,1); 551 | z1p=(4,12);z1pt=(1,2) 552 | add_char("l", 7, [ 553 | _draw2([(z0,sklon2),1,(z1p,z1pt),1.5,(z1,left),1,(z2,sklon1),1,(z3,sklon1)]), 554 | shift(dotah, (z3[0],0)) 555 | ]) 556 | add_char("lcaron", 7, [ 557 | _draw2([(z0,sklon2),1,(z1p,z1pt),1.5,(z1,left),1,(z2,sklon1),1,(z3,sklon1)]), 558 | shift(dotah, (z3[0],0)), 559 | shift(hacekl, (5.5, 2)) 560 | ]) 561 | add_char("lacute", 7, [ 562 | _draw2([(z0,sklon2),1,(z1p,z1pt),1.5,(z1,left),1,(z2,sklon1),1,(z3,sklon1)]), 563 | shift(dotah, (z3[0],0)), 564 | shift(capcarka, (4, 0)) 565 | ]) 566 | 567 | 568 | 569 | #beginchar("m", 15.7u#, 7u#, 0); 570 | # z0=(0,6); z1=(3,5); z1d=(1.5,0); z2=(6,5); z2d=(4.5,0); 571 | # z3=(9,5); z4=(7.7,1); 572 | # z1n=(2.5,7); z2n=(5.5,7); z3n=(8.5,7); 573 | # draw z0{sklon2}..z1n{right}..z1{sklon1}..{sklon1}z1d; 574 | # draw z1{-sklon1}..z2n{right}..z2{sklon1}..{sklon1}z2d; 575 | # draw z2{-sklon1}..z3n{right}..z3{sklon1}..{sklon1}z4; 576 | # dotah shifted (x4,0); 577 | #endchar; 578 | z0=(0,6); z1=(3,5); z1d=(1.5,0); z2=(6,5); z2d=(4.5,0); 579 | z3=(9,5); z4=(7.7,1); 580 | z1n=(2.5,7); z2n=(5.5,7); z3n=(8.5,7); 581 | add_char("m", 15.7, [ 582 | _draw2([(z0, sklon2),1,(z1n,right),1,(z1,sklon1),1,(z1d,sklon1)]), 583 | _draw2([(z1,-sklon1),1,(z2n,right),1,(z2,sklon1),1,(z2d,sklon1)]), 584 | _draw2([(z2,-sklon1),1,(z3n,right),1,(z3,sklon1),1,(z4 ,sklon1)]), 585 | shift(dotah, (z4[0],0)) 586 | ]) 587 | 588 | 589 | #beginchar("n", 12.7u#, 7u#, 0); 590 | # z0=(0,6); z1=(3,5); z1d=(1.5,0); z2=(6,5); z3=(4.7,1); 591 | # z1n=(2.5,7); z2n=(5.5,7); 592 | # draw z0{sklon2}..z1n{right}..z1{sklon1}..{sklon1}z1d; 593 | # draw z1{-sklon1}..z2n{right}..z2{sklon1}..{sklon1}z3; 594 | # dotah shifted (x3,0); 595 | #endchar; 596 | z0=(0,6); z1=(3,5); z1d=(1.5,0); z2=(6,5); z3=(4.7,1); 597 | z1n=(2.5,7); z2n=(5.5,7); 598 | add_char("n", 12.7, [ 599 | _draw2([(z0, sklon2),1,(z1n,right),1,(z1,sklon1),1,(z1d,sklon1)]), 600 | _draw2([(z1,-sklon1),1,(z2n,right),1,(z2,sklon1),1,(z3,sklon1)]), 601 | shift(dotah, (z3[0],0)) 602 | ]) 603 | add_char("ncaron", 12.7, [ 604 | _draw2([(z0, sklon2),1,(z1n,right),1,(z1,sklon1),1,(z1d,sklon1)]), 605 | _draw2([(z1,-sklon1),1,(z2n,right),1,(z2,sklon1),1,(z3,sklon1)]), 606 | shift(dotah, (z3[0],0)), 607 | shift(hacek, (4,0)) 608 | ]) 609 | 610 | #beginchar("o", 8u#, 7u#, 0); 611 | # z0=(0,6); z1=(3,7); z2=(-1,0); z3=(8,6); 612 | # z1p=(1.5,6.9); z2p=(2,6); 613 | # draw z1{left}..z1p..z0{-sklon2}..tension1.5.. 614 | # z2{right}..tension1.5..{-sklon1}z1{left}..z2p{down}..{sklon2}z3; 615 | #endchar; 616 | z0=(0,6); z1=(3,7); z2=(-1,0); z3=(8,6); 617 | z1p=(1.5,6.9); z2p=(2,6); z1t=(-4,-1) 618 | add_char("o", 8, [ 619 | _draw2([(z1,left),1,(z1p,z1t),1,(z0,-sklon2),1.5, 620 | (z2,right),1.5,(-sklon1,z1,left),1,(z2p,down),1,(z3,sklon2)]), 621 | ]) 622 | add_char("oacute", 8, [ 623 | _draw2([(z1,left),1,(z1p,z1t),1,(z0,-sklon2),1.5, 624 | (z2,right),1.5,(-sklon1,z1,left),1,(z2p,down),1,(z3,sklon2)]), 625 | shift(carka, (3,0)) 626 | ]) 627 | add_char("ocircumflex", 8, [ 628 | _draw2([(z1,left),1,(z1p,z1t),1,(z0,-sklon2),1.5, 629 | (z2,right),1.5,(-sklon1,z1,left),1,(z2p,down),1,(z3,sklon2)]), 630 | shift(vokan, (0,0)) 631 | ]) 632 | 633 | #beginchar(onarrow, 6u#, 7u#, 0); 634 | # z0=(0,6); z1=(3,7); z2=(-1,0); z3=(6,6); 635 | # z1p=(1.5,6.9); z2p=(2,6); 636 | # draw z1{left}..z1p..z0{-sklon2}..tension1.5.. 637 | # z2{right}..tension1.5..{-sklon1}z1{left}..z2p{down}..{sklon2}z3; 638 | #endchar; 639 | z0=(0,6); z1=(3,7); z2=(-1,0); z3=(6,6); 640 | z1p=(1.5,6.9); z2p=(2,6); z1t=(-4,-1) 641 | add_char("onarrow", 6, [ 642 | _draw2([(z1,left),1,(z1p,z1t),1,(z0,-sklon2),1.5, 643 | (z2,right),1.5,(-sklon1,z1,left),1,(z2p,down),1,(z3,sklon2)]), 644 | ]) 645 | add_char("oacutenarrow", 6, [ 646 | _draw2([(z1,left),1,(z1p,z1t),1,(z0,-sklon2),1.5, 647 | (z2,right),1.5,(-sklon1,z1,left),1,(z2p,down),1,(z3,sklon2)]), 648 | shift(carka, (3,0)) 649 | ]) 650 | # FIXME: slabikar.mf has otoceny_hacek instead of vokan, a bug 651 | add_char("ocircumflexnarrow", 6, [ 652 | _draw2([(z1,left),1,(z1p,z1t),1,(z0,-sklon2),1.5, 653 | (z2,right),1.5,(-sklon1,z1,left),1,(z2p,down),1,(z3,sklon2)]), 654 | shift(vokan, (0,0)) 655 | ]) 656 | 657 | 658 | #beginchar("p", 10.2u#, 8u#, 7u#); 659 | # z0=(0,6); 660 | # z1=(.5,4); z2n=(3,7); z2=(3.5,6); z3=(2.2,1); 661 | # z5=(-2.5,-7); 662 | # (z1-z4)=whatever*(z1-z5); y4=8; 663 | # draw z0{sklon2}..{-sklon1}z4{sklon1}--z5; 664 | # draw z1{-sklon1}..z2n{right}..z2{sklon1}..{sklon1}z3; 665 | # dotah shifted (x3,0); 666 | #endchar; 667 | z0=(0,6); 668 | z1=(.5,4); z2n=(3,7); z2=(3.5,6); z3=(2.2,1); 669 | z5=(-2.5,-7); 670 | z4 = whatever_y(z1, array(z1)-array(z5), 8) 671 | add_char("p", 10.2, [ 672 | _draw2([(z0, sklon2),1,(-sklon1,z4,sklon1),None,(z5,None)]), 673 | _draw2([(z1,-sklon1),1,(z2n,right),1,(z2,sklon1),1,(z3,sklon1)]), 674 | shift(dotah, (z3[0],0)) 675 | ]) 676 | 677 | #beginchar("q", 9u#, 7u#, 7u#); 678 | # z0=(0,6); z1=(3,7); z2=(-1,0); 679 | # z1p=(1.5,6.9); 680 | # z3=(1.1,-.5); z4-z1 = whatever*(z3-z1); y4=-7; 681 | # z5=(9,6); 682 | # draw z1{left}..z1p..z0{-sklon2}..tension1.5.. 683 | # z2{right}..tension1.5..{-sklon1}z1{sklon1}..{sklon1}z3..{sklon1}z4; 684 | # draw z3{-sklon1}..tension2..{sklon2}z5; 685 | #endchar; 686 | z0=(0,6); z1=(3,7); z2=(-1,0); 687 | z1p=(1.5,6.9);z1pt=(-4,-1) 688 | z3=(1.1,-.5); z4 = whatever_y(z1, array(z3)-array(z1), -7) 689 | z5=(9,6); 690 | add_char("q", 9, [ 691 | _draw2([(z1,left),1,(z1p,z1pt),1,(z0,-sklon2),1.5, 692 | (z2,right),1.5,(-sklon1,z1,sklon1),1,(z3,sklon1),1,(z4,sklon1)]), 693 | _draw2([(z3,-sklon1),2,(z5,sklon2)]), 694 | ]) 695 | 696 | #beginchar("r", 8.4u#, 7u#, 0); 697 | # z0=(0,6); z1=(.5,7); z2=(2,7); z3=(.4,1); 698 | # draw z0{sklon2}..{-sklon1}z1{sklon1}..{-sklon1}z2{sklon1}..{sklon1}z3; 699 | # dotah shifted (x3,0); 700 | #endchar; 701 | z0=(0,6); z1=(.5,7); z2=(2,7); z3=(.4,1); 702 | add_char("r", 8.4, [ 703 | _draw2([(z0, sklon2),1,(-sklon1,z1,sklon1),1,(-sklon1,z2,sklon1),1, 704 | (z3,sklon1)]), 705 | shift(dotah, (z3[0],0)) 706 | ]) 707 | add_char("rcaron", 8.4, [ 708 | _draw2([(z0, sklon2),1,(-sklon1,z1,sklon1),1,(-sklon1,z2,sklon1),1, 709 | (z3,sklon1)]), 710 | shift(dotah, (z3[0],0)), 711 | shift(hacek, (1.4,0)) 712 | ]) 713 | add_char("racute", 8.4, [ 714 | _draw2([(z0, sklon2),1,(-sklon1,z1,sklon1),1,(-sklon1,z2,sklon1),1, 715 | (z3,sklon1)]), 716 | shift(dotah, (z3[0],0)), 717 | shift(carka, (1.4,0)) 718 | ]) 719 | 720 | #beginchar("s", 2u#, 7u#, 0); 721 | # z0=(0,6); z1=(.5,7); z2=(-.5,1); z3=(-2,0); z4=(-3,2); z5=(7,6); 722 | # draw z0{sklon2}..{-sklon1}z1{sklon1}..z2{-sklon2}..z3{left}..{(-1,3)}z4; 723 | #endchar; 724 | z0=(0,6); z1=(.5,7); z2=(-.5,1); z3=(-2,0); z4=(-3,2); z5=(7,6); 725 | add_char("s", 2, [ 726 | _draw2([(z0, sklon2),1,(-sklon1,z1,sklon1),1,(z2,-sklon2),1, 727 | (z3,left), 1, (z4,(-1,3))]), 728 | ]) 729 | add_char("scaron", 2, [ 730 | _draw2([(z0, sklon2),1,(-sklon1,z1,sklon1),1,(z2,-sklon2),1, 731 | (z3,left), 1, (z4,(-1,3))]), 732 | shift(hacek, (0,0)) 733 | ]) 734 | 735 | #beginchar(sleft, 9u#, 7u#, 0); %% koncove s 736 | # z0=(0,0); z1=(7.5,7); z2=(6.5,1); z3=(5,0); z4=(3.5,3); 737 | # draw z0..{sklon2}z1{-sklon2}..z2{-sklon2}..z3{left}..{(-1,3)}z4; 738 | #endchar; 739 | # FIXME: the z0t here seems correct; slabikar.mf is bent, and the end of `s` 740 | # ends up being across the line, which seems like a bug 741 | z0=(0,0); z1=(7.5,7); z2=(6.5,1); z3=(5,0); z4=(3.5,3); 742 | z0t=array(z4)-array(z0) 743 | add_char("sleft", 9, [ 744 | _draw2([(z0, z0t),1,(sklon2,z1,-sklon2),1,(z2,-sklon2),1, 745 | (z3,left), 1, (z4,(-1,3))]), 746 | ]) 747 | add_char("scaronleft", 9, [ 748 | _draw2([(z0, z0t),1,(sklon2,z1,-sklon2),1,(z2,-sklon2),1, 749 | (z3,left), 1, (z4,(-1,3))]), 750 | shift(hacek, (8,0)) 751 | ]) 752 | 753 | #beginchar(sdepth, 2u#, 7u#, 0); 754 | # z0=(0,6); z1=(.5,7); z2=(-.5,1); z3=(-2,0); z4=(-3.5,2.5); z5=(7,6); 755 | # draw z0{sklon2}..{-sklon1}z1{sklon1}..z2{-sklon2}..z3{left}..{(-1,3)}z4; 756 | #endchar; 757 | z0=(0,6); z1=(.5,7); z2=(-.5,1); z3=(-2,0); z4=(-3.5,2.5); z5=(7,6); 758 | add_char("sdepth", 2, [ 759 | _draw2([(z0, sklon2),1,(-sklon1,z1,sklon1),1,(z2,-sklon2),1, 760 | (z3,left), 1, (z4,(-1,3))]), 761 | ]) 762 | add_char("scarondepth", 2, [ 763 | _draw2([(z0, sklon2),1,(-sklon1,z1,sklon1),1,(z2,-sklon2),1, 764 | (z3,left), 1, (z4,(-1,3))]), 765 | shift(hacek, (0,0)) 766 | ]) 767 | 768 | if t_style == 1: 769 | #beginchar("t", 9u#, 14u#, 0); 770 | # z0=(0,6); z1=(4.5,14); z2=(1,0); z3=(9,6); 771 | # z10=(0,1); 772 | # draw z0{sklon2}..tension2..{-sklon1}z1--z2{-sklon1}.. 773 | # z10..z2{right}..z3{sklon2}; 774 | #endchar; 775 | z0=(0,6); z1=(4.5,14); z2=(1,0); z3=(9,6); 776 | z10=(0,1);z10t=(-5,-6) 777 | add_char("t", 9, [ 778 | _draw2([(z0,sklon2),2,(z1,-sklon1),None,(z2,-sklon1),1, 779 | (z10,z10t),1,(z2,right),1,(z3,sklon2)]) 780 | ]) 781 | add_char("tcaron", 9, [ 782 | _draw2([(z0,sklon2),2,(z1,-sklon1),None,(z2,-sklon1),1, 783 | (z10,z10t),1,(z2,right),1,(z3,sklon2)]), 784 | shift(hacek, (5.5,2)) 785 | ]) 786 | elif t_style == 2: 787 | z0=(0,6); z1=(4.5,14); z2=(1.25,1); 788 | letter = _draw2([(z0,sklon2),2,(z1,-sklon1),None,(z2,-sklon1)]) 789 | z3=(-2.5,7); z4=(9.25+z3[0], z3[1]) 790 | add_char("t", 9.25, [ 791 | shift(letter, (0,0)), 792 | shift(dotah, (z2[0],0)), 793 | _draw2([(z3,None),None,(z4,None)]), 794 | ]) 795 | add_char("tcaron", 9.25, [ 796 | shift(letter, (0,0)), 797 | shift(dotah, (z2[0],0)), 798 | _draw2([(z3,None),None,(z4,None)]), 799 | shift(hacek, (5.5,2)) 800 | ]) 801 | else: 802 | raise Exception("Unsupported style") 803 | 804 | #beginchar("u", 10u#, 7u#, 0); 805 | # z0=(0,6); z1=(.5,7); z2=(-1,1); z3=(0,0); z4=(3.5,7); z5=(2,1); 806 | # draw z0{sklon2}..{-sklon1}z1{sklon1}..z2{sklon1}..z3{right}..tension2.. 807 | # {-sklon1}z4{sklon1}..{sklon1}z5; 808 | # dotah shifted (x5,0); 809 | #endchar; 810 | z0=(0,6); z1=(.5,7); z2=(-1,1); z3=(0,0); z4=(3.5,7); z5=(2,1); 811 | add_char("u", 10, [ 812 | _draw2([(z0, sklon2),1,(-sklon1,z1,sklon1),1,(z2,sklon1),1, 813 | (z3,right),2,(-sklon1,z4,sklon1),1,(z5,sklon1)]), 814 | shift(dotah, (z5[0],0)) 815 | ]) 816 | add_char("uacute", 10, [ 817 | _draw2([(z0, sklon2),1,(-sklon1,z1,sklon1),1,(z2,sklon1),1, 818 | (z3,right),2,(-sklon1,z4,sklon1),1,(z5,sklon1)]), 819 | shift(dotah, (z5[0],0)), 820 | shift(carka, (2.5,0)) 821 | ]) 822 | add_char("uring", 10, [ 823 | _draw2([(z0, sklon2),1,(-sklon1,z1,sklon1),1,(z2,sklon1),1, 824 | (z3,right),2,(-sklon1,z4,sklon1),1,(z5,sklon1)]), 825 | shift(dotah, (z5[0],0)), 826 | shift(krouzek, (2.5,0)) 827 | ]) 828 | 829 | #beginchar("v", 11u#, 7u#, 0); 830 | # z0=(0,6); z1=(2.5,6); z11=(2,7); z2=(1,1); 831 | # z4=(2,0); z5=(5,7); z6=(11,6); 832 | # z5p=(4.5,6); 833 | # draw z0{sklon2}..z11{right}..z1{sklon1}..z2{sklon1}.. 834 | # z4{right}..tension3..z5{left}..z5p{down}.. 835 | # tension2..{sklon2}z6 836 | #endchar; 837 | z0=(0,6); z1=(2.5,6); z11=(2,7); z2=(1,1); 838 | z4=(2,0); z5=(5,7); z6=(11,6); 839 | z5p=(4.5,6); 840 | add_char("v", 11, [ 841 | _draw2([(z0,sklon2),1,(z11,right),1,(z1,sklon1),1,(z2,sklon1),1, 842 | (z4,right),3,(z5,left),1,(z5p,down),2,(z6,sklon2)]) 843 | ]) 844 | 845 | #beginchar(vnarrow, 9u#, 7u#, 0); 846 | # z0=(0,6); z1=(2.5,6); z11=(2,7); z2=(1,1); 847 | # z4=(2,0); z5=(5,7); z6=(9,6); 848 | # z5p=(4.5,6); 849 | # draw z0{sklon2}..z11{right}..z1{sklon1}..z2{sklon1}.. 850 | # z4{right}..tension3..z5{left}..z5p{down}.. 851 | # tension2..{sklon2}z6 852 | #endchar; 853 | z0=(0,6); z1=(2.5,6); z11=(2,7); z2=(1,1); 854 | z4=(2,0); z5=(5,7); z6=(9,6); 855 | z5p=(4.5,6); 856 | add_char("vnarrow", 9, [ 857 | _draw2([(z0,sklon2),1,(z11,right),1,(z1,sklon1),1,(z2,sklon1),1, 858 | (z4,right),3,(z5,left),1,(z5p,down),2,(z6,sklon2)]) 859 | ]) 860 | 861 | 862 | #beginchar("w", 14u#, 7u#, 0); 863 | # z0=(0,6); z1=(2.5,6); z11=(2,7); 864 | # z2=(1,1); z3=(2,0); z4=(5.5,7); 865 | # z5=(4,1); z6=(5,0); z7=(8,7); z8=(14,6); 866 | # z7p=(7.5,6); 867 | # draw z0{sklon2}..z11{right}..z1{sklon1}..z2{sklon1}.. 868 | # z3{right}..tension2..{-sklon1}z4{sklon1}.. 869 | # z5{sklon1}..z6{right}..tension3..z7{left}..z7p{down}.. 870 | # tension2..{sklon2}z8 871 | #endchar; 872 | z0=(0,6); z1=(2.5,6); z11=(2,7); 873 | z2=(1,1); z3=(2,0); z4=(5.5,7); 874 | z5=(4,1); z6=(5,0); z7=(8,7); z8=(14,6); 875 | z7p=(7.5,6); 876 | add_char("w", 14, [ 877 | _draw2([(z0,sklon2),1,(z11,right),1,(z1,sklon1),1,(z2,sklon1),1, 878 | (z3,right),2,(-sklon1,z4,sklon1),1, 879 | (z5,sklon1),1,(z6,right),3,(z7,left),1,(z7p,down),2,(z8,sklon2)]) 880 | ]) 881 | 882 | #beginchar(wnarrow, 12u#, 7u#, 0); 883 | # z0=(0,6); z1=(2.5,6); z11=(2,7); 884 | # z2=(1,1); z3=(2,0); z4=(5.5,7); 885 | # z5=(4,1); z6=(5,0); z7=(8,7); z8=(12,6); 886 | # z7p=(7.5,6); 887 | # draw z0{sklon2}..z11{right}..z1{sklon1}..z2{sklon1}.. 888 | # z3{right}..tension2..{-sklon1}z4{sklon1}.. 889 | # z5{sklon1}..z6{right}..tension3..z7{left}..z7p{down}.. 890 | # tension2..{sklon2}z8 891 | #endchar; 892 | z0=(0,6); z1=(2.5,6); z11=(2,7); 893 | z2=(1,1); z3=(2,0); z4=(5.5,7); 894 | z5=(4,1); z6=(5,0); z7=(8,7); z8=(12,6); 895 | z7p=(7.5,6); 896 | add_char("wnarrow", 12, [ 897 | _draw2([(z0,sklon2),1,(z11,right),1,(z1,sklon1),1,(z2,sklon1),1, 898 | (z3,right),2,(-sklon1,z4,sklon1),1, 899 | (z5,sklon1),1,(z6,right),3,(z7,left),1,(z7p,down),2,(z8,sklon2)]) 900 | ]) 901 | 902 | 903 | #beginchar("x", 5u#, 7u#, 0); 904 | # z0=(0,6); z1=(1,7); 905 | # z2=(-1.5,7); z3=(-3,1); 906 | # draw z0{sklon2}..z1; 907 | # draw z2{sklon1}..{sklon1}z3; 908 | # dotah shifted (x3,0); 909 | #endchar; 910 | z0=(0,6); z1=(1,7); 911 | z2=(-1.5,7); z3=(-3,1); 912 | add_char("x", 5, [ 913 | _draw2([(z0,sklon2),1,(z1,sklon2)]), 914 | _draw2([(z2,sklon1),1,(z3,sklon1)]), 915 | shift(dotah, (z3[0],0)) 916 | ]) 917 | 918 | #beginchar("y", 11u#, 7u#, 7u#); 919 | # z0=(0,6); z1=(2.5,6); z11=(2,7); 920 | # z2=(1,1); z3=(2,0); z4=(5.5,7); 921 | # draw z0{sklon2}..z11{right}..z1{sklon1}..z2{sklon1}.. 922 | # z3{right}..tension2..{-sklon1}z4; 923 | # smycka shifted (x4,0); 924 | #endchar; 925 | z0=(0,6); z1=(2.5,6); z11=(2,7); 926 | z2=(1,1); z3=(2,0); z4=(5.5,7); 927 | add_char("y", 11, [ 928 | _draw2([(z0,sklon2),1,(z11,right),1,(z1,sklon1),1,(z2,sklon1),1, 929 | (z3,right),2,(z4,-sklon1)]), 930 | shift(smycka, (z4[0],0)) 931 | ]) 932 | add_char("yacute", 11, [ 933 | _draw2([(z0,sklon2),1,(z11,right),1,(z1,sklon1),1,(z2,sklon1),1, 934 | (z3,right),2,(z4,-sklon1)]), 935 | shift(smycka, (z4[0],0)), 936 | shift(carka, (4.5,0)) 937 | ]) 938 | 939 | def svg2mf(x): 940 | h = 800 941 | return (x[0]/scale, (h-x[1])/scale) 942 | 943 | 944 | if z_style == 1: 945 | #beginchar("z", 11u#, 7u#, 0); 946 | # z0=(0,6); z1=(1.5,7); z2=(4,7); z3=(1,0); 947 | # z4=(4,0); z5=(11,6); 948 | # draw z0{sklon2}..z1{right}..{-sklon1}z2{sklon1}.. 949 | # {sklon1}z3{-sklon1}..z4{right}..tension1.5..{sklon2}z5; 950 | #endchar; 951 | z0=(0,6); z1=(1.5,7); z2=(4,7); z3=(1,0); 952 | z4=(4,0); z5=(11,6); 953 | add_char("z", 11, [ 954 | _draw2([(z0,sklon2),1,(z1,right),1,(-sklon1,z2,sklon1),1, 955 | (sklon1,z3,-sklon1),1,(z4,right),1.5,(z5,sklon2)]), 956 | ]) 957 | add_char("zcaron", 11, [ 958 | _draw2([(z0,sklon2),1,(z1,right),1,(-sklon1,z2,sklon1),1, 959 | (sklon1,z3,-sklon1),1,(z4,right),1.5,(z5,sklon2)]), 960 | shift(hacek, (2.5,0)) 961 | ]) 962 | elif z_style == 2: 963 | z0=(0,6); z1=(1.5,7); z2=svg2mf((138,575)); z3=(1,0); 964 | z4=svg2mf((130, 800)); z5=(11,6); 965 | smycka2 = _draw2([((-2,0),sklon1),1,((-3.1,-4),sklon1),1, 966 | ((-5.3,-7),left),1,((-5.5,-5),-sklon1),1, 967 | ((-2,0),(6,5)),1,((5.5,6),sklon2)]) 968 | letter = _draw2([(z0,sklon2),1,(z1,right),1,(z2,sklon1),1, 969 | (sklon1,z3,dir_(-330)),1,(z4,sklon1)]) 970 | add_char("z", z4[0]+7.5, [ 971 | shift(letter, (0,0)), 972 | shift(smycka2, (z4[0]+2,0)) 973 | ]) 974 | add_char("zcaron", z4[0]+7.5, [ 975 | shift(letter, (0,0)), 976 | shift(smycka2, (z4[0]+2,0)), 977 | shift(hacek, (2.5,0)) 978 | ]) 979 | elif z_style == 3: 980 | z0=(0,6); z1=(1.5,7); z2=(4,7); z2b=(1,1); z3=(-0.5,0); z3b=(-0.5, 1) 981 | z4=(4,0); z5=(11,6); 982 | z2bt=array(z2b)-array(z2) 983 | letter = _draw2([(z0,sklon2),1,(z1,right),1,(-z2bt,z2,None),None, 984 | (z2b,z2bt),1, 985 | (z3,left),1,(z3b,right),1,(z4,right),1.5,(z5,sklon2)]) 986 | add_char("z", 11, [ 987 | shift(letter, (0,0)), 988 | ]) 989 | add_char("zcaron", 11, [ 990 | shift(letter, (0,0)), 991 | shift(hacek, (2.5,0)) 992 | ]) 993 | elif z_style == 4: 994 | z0=(0,6); z1=(0.5,7); z2=(4,7); z2b=(1,1); z3=(-0.5,0); z3b=(-0.5, 1) 995 | z4=(4,0); z5=(11,6); 996 | z2bt=array(z2b)-array(z2) 997 | letter = _draw2([(z0,sklon2),1,(-sklon1,z1,sklon1),1,(-z2bt,z2,None),None, 998 | (z2b,z2bt),1, 999 | (z3,left),1,(z3b,right),1,(z4,right),1.5,(z5,sklon2)]) 1000 | add_char("z", 11, [ 1001 | shift(letter, (0,0)), 1002 | ]) 1003 | add_char("zcaron", 11, [ 1004 | shift(letter, (0,0)), 1005 | shift(hacek, (2.5,0)) 1006 | ]) 1007 | else: 1008 | raise Exception("Unsupported style") 1009 | 1010 | ################################################################################ 1011 | # Uppercase 1012 | 1013 | #beginchar("A", 11.4u#, 14u#, 0); 1014 | # z0=(0,6); z1=(7,14); z2=(1,0); z3=(3.4,1); 1015 | # z1p=(6,13.9); 1016 | # draw z1{left}..z1p..z0{sklon1}.. 1017 | # z2{right}..tension2.5..{-sklon1}z1{sklon1}..z3{sklon1}; 1018 | # dotah shifted (x3,0); 1019 | #endchar; 1020 | z0=(0,6); z1=(7,14); z2=(1,0); z3=(3.4,1); 1021 | z1p=(6,13.9);z1t=(-4,-1) 1022 | add_char("A_", 11.4, [ 1023 | _draw2([(z1,left),1,(z1p,z1t),1,(z0,sklon1),1, 1024 | (z2,right),2.5,(-sklon1,z1,sklon1),1,(z3,sklon1)]), 1025 | shift(dotah, (z3[0],0)) 1026 | ]) 1027 | add_char("A_acute", 11.4, [ 1028 | _draw2([(z1,left),1,(z1p,z1t),1,(z0,sklon1),1, 1029 | (z2,right),2.5,(-sklon1,z1,sklon1),1,(z3,sklon1)]), 1030 | shift(dotah, (z3[0],0)), 1031 | shift(capcarka, (6,0)) 1032 | ]) 1033 | add_char("A_dieresis", 11.4, [ 1034 | _draw2([(z1,left),1,(z1p,z1t),1,(z0,sklon1),1, 1035 | (z2,right),2.5,(-sklon1,z1,sklon1),1,(z3,sklon1)]), 1036 | shift(dotah, (z3[0],0))] + 1037 | dvetecky(3,6) 1038 | ) 1039 | 1040 | #beginchar("B", 9u#, 14u#, 0); 1041 | # z0=(0,6); z1=(8,14); z2=(1,0); z2p=(3,3); 1042 | # z3=(0,4); z4=(6,8); z4l=(x4-1,y4); 1043 | # z5=(8.5,4); z6=(5,0); z7=(3.5,2); 1044 | # draw z1{left}..z2p{sklon1}..z2{left}..z0{-sklon1}.. 1045 | # z1{right}..{dir190}z4..z4l{up}..z4{dir-20}..z5{sklon1}..z6{left}..z7; 1046 | #endchar; 1047 | z0=(0,6); z1=(8,14); z2=(1,0); z2p=(3,3); 1048 | z3=(0,4); z4=(6,8); z4l=(z4[0]-1,z4[1]); 1049 | z5=(8.5,4); z6=(5,0); z7=(3.5,2); z7t=(1,2) 1050 | add_char("B_", 9, [ 1051 | _draw2([(z1,left),1,(z2p,sklon1),1,(z2,left),1,(z0,-sklon1),1, 1052 | (z1,right),1,(z4,dir_(190)),1,(z4l,up),1,(z4,dir_(-20)),1,(z5,sklon1), 1053 | 1,(z6,left),1,(z7,z7t)]) 1054 | ]) 1055 | 1056 | #beginchar("C", 9.5u#, 14u#, 0); 1057 | # z0=(0,6); z1=(5,12.5); z2=(x1+.3,11); z3=(x1+.1,14); 1058 | # z4=(1.5,0); z5=(x4+8,6); 1059 | # draw z1{sklon1}..z2{right}..tension1.5..z3{left}..tension2.. 1060 | # z0{sklon1}..z4{right}..tension1.5..{sklon2}z5; 1061 | #endchar; 1062 | z0=(0,6); z1=(5,12.5); z2=(z1[0]+.3,11); z3=(z1[0]+.1,14); 1063 | z4=(1.5,0); z5=(z4[0]+8,6); 1064 | add_char("C_", 9.5, [ 1065 | _draw2([(z1,sklon1),1,(z2,right),1.5,(z3,left),2, 1066 | (z0,sklon1),1,(z4,right),1.5,(z5,sklon2)]) 1067 | ]) 1068 | add_char("C_caron", 9.5, [ 1069 | _draw2([(z1,sklon1),1,(z2,right),1.5,(z3,left),2, 1070 | (z0,sklon1),1,(z4,right),1.5,(z5,sklon2)]), 1071 | shift(hacek, (5,6)) 1072 | ]) 1073 | 1074 | #beginchar("D", 8u#, 14u#, 0); 1075 | # z1=(9,14); z2=(3,3); z3=(1,0); z4=(.5,0); z4n=(x4,1); 1076 | # z5=(4,0); z6=(7,4); z7=(6,14); z8=(3.5,13); z9=(3.5,9); 1077 | # z10=(5.5,12); 1078 | # draw z1{-sklon2}..z2{sklon1}..z3..z4{left}..z4n{right}.. 1079 | # z5{right}..z6{-sklon1}..z7{left}.. 1080 | # z8{-sklon2}..z9{right}..{-sklon1}z10; 1081 | #endchar; 1082 | z1=(9,14); z2=(3,3); z3=(1,0); z4=(.5,0); z4n=(z4[0],1); 1083 | z5=(4,0); z6=(7,4); z7=(6,14); z8=(3.5,13); z9=(3.5,9); 1084 | z10=(5.5,12); 1085 | z3t=(-4,-1) 1086 | add_char("D_", 8, [ 1087 | _draw2([(z1,-sklon2),1,(z2,sklon1),1,(z3,z3t),1,(z4,left),1,(z4n,right),1, 1088 | (z5,right),1,(z6,-sklon1),1,(z7,left),1, 1089 | (z8,-sklon2),1,(z9,right),1,(z10,-sklon1)]), 1090 | ]) 1091 | add_char("D_caron", 8, [ 1092 | _draw2([(z1,-sklon2),1,(z2,sklon1),1,(z3,z3t),1,(z4,left),1,(z4n,right),1, 1093 | (z5,right),1,(z6,-sklon1),1,(z7,left),1, 1094 | (z8,-sklon2),1,(z9,right),1,(z10,-sklon1)]), 1095 | shift(hacek, (7,6)) 1096 | ]) 1097 | 1098 | #beginchar("E", 9.5u#, 14u#, 0); 1099 | # z0=(0,6); z1=(4,12.5); z2=(x1+.3,11); z3=(x1+.1,14); 1100 | # z6=(2,8.5); z6n=(x6+1,y6); 1101 | # z4=(1.5,0); z5=(x4+8,6); 1102 | # draw z1{sklon1}..z2{right}..tension1.5..z3{left}..tension2.. 1103 | # z6..z6n{up}..z6.. 1104 | # z0..tension1.5and1..z4{right}..tension1.5..{sklon2}z5; 1105 | #endchar; 1106 | z0=(0,6); z1=(4,12.5); z2=(z1[0]+.3,11); z3=(z1[0]+.1,14); 1107 | z6=(2,8.5); z6n=(z6[0]+1,z6[1]); 1108 | z4=(1.5,0); z5=(z4[0]+8,6); 1109 | z6t=(1,-3); z6t2=(-1,-1); z0t=(-4,-7) 1110 | add_char("E_", 9.5, [ 1111 | _draw2([(z1,sklon1),1,(z2,right),1.5,(z3,left),2, 1112 | (z6,z6t),1,(z6n,up),1,(z6,z6t2),1, 1113 | (z0,z0t),1.3,(z4,right),1.5,(z5,sklon2)]), 1114 | ]) 1115 | add_char("E_acute", 9.5, [ 1116 | _draw2([(z1,sklon1),1,(z2,right),1.5,(z3,left),2, 1117 | (z6,z6t),1,(z6n,up),1,(z6,z6t2),1, 1118 | (z0,z0t),1.3,(z4,right),1.5,(z5,sklon2)]), 1119 | shift(capcarka, (5,0)) 1120 | ]) 1121 | add_char("E_caron", 9.5, [ 1122 | _draw2([(z1,sklon1),1,(z2,right),1.5,(z3,left),2, 1123 | (z6,z6t),1,(z6n,up),1,(z6,z6t2),1, 1124 | (z0,z0t),1.3,(z4,right),1.5,(z5,sklon2)]), 1125 | shift(hacek, (4.5,6)) 1126 | ]) 1127 | 1128 | #beginchar("F", 5u#, 14u#, 0); charic := 7u#; 1129 | # z1=(4,12.5); z2=(3,10); z3=(2.3,12.5); z4=(4,14); 1130 | # z5=(7,13.5); z6=(12,14); 1131 | # z7=(4,4); z8=(1,0); z9=(0,3); 1132 | # z10=(2,7); z11=(6,9); z12=(6.5,7); 1133 | # draw z1{sklon1}..z2..z3{-sklon1}..z4{right}..z5..{right}z6; 1134 | # draw z5{-sklon2}..z7{sklon1}..z8{left}..{-sklon1}z9; 1135 | # draw z10..z11{right}..{sklon1}z12; 1136 | #endchar; 1137 | z1=(4,12.5); z2=(3,10); z3=(2.3,12.5); z4=(4,14); 1138 | z5=(7,13.5); z6=(12,14); 1139 | z7=(4,4); z8=(1,0); z9=(0,3); 1140 | z10=(2,7); z11=(6,9); z12=(6.5,7); 1141 | z2t=(-1,0); z5t=(4,-1); z10t=(1,1) 1142 | add_char("F_", 5, [ 1143 | _draw2([(z1,sklon1),1,(z2,z2t),1,(z3,-sklon1),1,(z4,right),1,(z5,z5t),1, 1144 | (z6,right)]), 1145 | _draw2([(z5,-sklon2),1,(z7,sklon1),1,(z8,left),1,(z9,-sklon1)]), 1146 | _draw2([(z10,z10t),1,(z11,right),1,(z12,sklon1)]) 1147 | ]) 1148 | 1149 | #beginchar("G", 10.5u#, 14u#, 7u#); 1150 | # z0=(0,6); z1=(5,12.5); z2=(x1+.3,11); z3=(x1+.1,14); 1151 | # z4=(1,0); z5=(x4+4,7); 1152 | # draw z1{sklon1}..z2{right}..tension1.5..z3{left}..tension2.. 1153 | # z0{sklon1}..z4{right}..tension1.5..{-sklon1}z5; 1154 | # smycka shifted (x5,0); 1155 | #endchar; 1156 | z0=(0,6); z1=(5,12.5); z2=(z1[0]+.3,11); z3=(z1[0]+.1,14); 1157 | z4=(1,0); z5=(z4[0]+4,7); 1158 | add_char("G_", 10.5, [ 1159 | _draw2([(z1,sklon1),1,(z2,right),1.5,(z3,left),2, 1160 | (z0,sklon1),1,(z4,right),1.5,(z5,-sklon1)]), 1161 | shift(smycka, (z5[0],0)) 1162 | ]) 1163 | 1164 | #beginchar("H", 13u#, 14u#, 0); 1165 | # z1=(1.5,11); z2=(4.5,14); z3=(5,12); z4=(2,1); 1166 | # z5=(1,0); z6=(0.5,3); z7=(6,8); 1167 | # z8=(9.5,11.5); z9=(9,14); z10=(8,13); z11=(5,1); 1168 | # draw z1{sklon2}..z2{right}..z3{sklon1}..{sklon1}z4.. 1169 | # z5{left}..z6{-sklon1}..tension1.5..z7..z8{-sklon1}.. 1170 | # z9{left}..z10{sklon1}..{sklon1}z11; 1171 | # dotah shifted (x11,0); 1172 | #endchar; 1173 | z1=(1.5,11); z2=(4.5,14); z3=(5,12); z4=(2,1); 1174 | z5=(1,0); z6=(0.5,3); z7=(6,8); 1175 | z8=(9.5,11.5); z9=(9,14); z10=(8,13); z11=(5,1); 1176 | z7t=(1,1) 1177 | add_char("H_", 13, [ 1178 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1),1, 1179 | (z5,left),1,(z6,-sklon1),1.5,(z7,z7t),1,(z8,-sklon1),1, 1180 | (z9,left),1,(z10,sklon1),1,(z11,sklon1)]), 1181 | shift(dotah, (z11[0],0)) 1182 | ]) 1183 | 1184 | #beginchar("I", 5u#, 14u#, 0); 1185 | # z1=(2.5,11); z2=(5.5,14); z3=(6,12); z4=(3.2,2); 1186 | # z5=(1,0); z6=(-.5,3); 1187 | # draw z1{sklon2}..z2{right}..z3{sklon1}..{sklon1}z4.. 1188 | # z5{left}..{up}z6; 1189 | #endchar; 1190 | z1=(2.5,11); z2=(5.5,14); z3=(6,12); z4=(3.2,2); 1191 | z5=(1,0); z6=(-.5,3); 1192 | add_char("I_", 5, [ 1193 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1),1, 1194 | (z5,left),1,(z6,up)]), 1195 | ]) 1196 | add_char("I_acute", 5, [ 1197 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1),1, 1198 | (z5,left),1,(z6,up)]), 1199 | shift(capcarka, (6,0)) 1200 | ]) 1201 | 1202 | #beginchar("J", 10.1u#, 14u#, 7u#); 1203 | # z1=(2.5,11); z2=(5.5,14); z3=(6,12); z4=(4.6,7); 1204 | # draw z1{sklon2}..z2{right}..z3{sklon1}..{sklon1}z4; 1205 | # smycka shifted (x4,0); 1206 | #endchar; 1207 | z1=(2.5,11); z2=(5.5,14); z3=(6,12); z4=(4.6,7); 1208 | add_char("J_", 10.1, [ 1209 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1)]), 1210 | shift(smycka, (z4[0],0)) 1211 | ]) 1212 | 1213 | #beginchar("K", 15u#, 14u#, 0); 1214 | # z1=(2.5,11); z2=(5.5,14); z3=(6,12); z4=(3.2,2); 1215 | # z5=(1,0); z6=(-.5,3); 1216 | # z7=(12,11); z8=(10,14); z9=(5,8); z9p=(x9+1,y9); 1217 | # z10=(9,0); z11=(15,6); 1218 | # draw z1{sklon2}..z2{right}..z3{sklon1}..{sklon1}z4.. 1219 | # z5{left}..{up}z6; 1220 | # draw z7{dir110}..z8{left}..tension2.. 1221 | # z9p{dir215}..z9{up}..z9p{dir-35}.. 1222 | # tension1.5..z10{right}..tension3..{sklon2}z11; 1223 | #endchar; 1224 | z1=(2.5,11); z2=(5.5,14); z3=(6,12); z4=(3.2,2); 1225 | z5=(1,0); z6=(-.5,3); 1226 | z7=(12,11); z8=(10,14); z9=(5,8); z9p=(z9[0]+1,z9[1]); 1227 | z10=(9,0); z11=(15,6); 1228 | add_char("K_", 15, [ 1229 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1),1, 1230 | (z5,left),1,(z6,up)]), 1231 | _draw2([(z7,dir_(110)),1,(z8,left),2,(z9p,dir_(215)),1,(z9,up),1, 1232 | (z9p,dir_(-35)),1.5,(z10,right),3,(z11,sklon2)]), 1233 | ]) 1234 | 1235 | #beginchar("L", 12u#, 14u#, 0); 1236 | # z1=(4,14); z2=(6,9); z3=(9,14); z4=(7,12); 1237 | # z5=(2,1); z5d=(.5,0); z5p=(-.5,.8); z6=(6,0); z7=(12,6); 1238 | # draw z1..z2{right}..tension1.7..z3{left}..z4{sklon1}.. 1239 | # z5..z5d{left}..z5p{up}..z5..z6{right}..tension2..{sklon2}z7; 1240 | #endchar; 1241 | z1=(4,14); z2=(6,9); z3=(9,14); z4=(7,12); 1242 | z5=(2,1); z5d=(.5,0); z5p=(-.5,.8); z6=(6,0); z7=(12,6); 1243 | z1t=(-1,-1); z5t=(-3,-4); z5t2=(8,-5) 1244 | add_char("L_", 12, [ 1245 | _draw2([(z1,z1t),1,(z2,right),1.7,(z3,left),1,(z4,sklon1),1, 1246 | (z5,z5t),1,(z5d,left),1,(z5p,up),1,(z5,z5t2),1,(z6,right),2, 1247 | (z7,sklon2)]), 1248 | ]) 1249 | add_char("L_acute", 12, [ 1250 | _draw2([(z1,z1t),1,(z2,right),1.7,(z3,left),1,(z4,sklon1),1, 1251 | (z5,z5t),1,(z5d,left),1,(z5p,up),1,(z5,z5t2),1,(z6,right),2, 1252 | (z7,sklon2)]), 1253 | shift(capcarka, (7,0)) 1254 | ]) 1255 | add_char("L_caron", 12, [ 1256 | _draw2([(z1,z1t),1,(z2,right),1.7,(z3,left),1,(z4,sklon1),1, 1257 | (z5,z5t),1,(z5d,left),1,(z5p,up),1,(z5,z5t2),1,(z6,right),2, 1258 | (z7,sklon2)]), 1259 | shift(hacek, (6,6)) 1260 | ]) 1261 | 1262 | #beginchar("M", 15u#, 14u#, 0); 1263 | # z1=(0.5,11); z2=(3.5,14); z3=(4,12); z4=(0.8,0); 1264 | # z5=(6.5,14); z6=(7,12); z7=(3.8,0); 1265 | # z8=(9.5,14); z9=(10,12); z10=(7,1); 1266 | # draw z1{sklon2}..z2{right}..z3{sklon1}..{sklon1}z4; 1267 | # draw z3{-sklon1}..tension1.5..z5{right}..z6{sklon1}..{sklon1}z7; 1268 | # draw z6{-sklon1}..tension1.5..z8{right}..z9{sklon1}..{sklon1}z10; 1269 | # dotah shifted (x10,0); 1270 | #endchar; 1271 | z1=(0.5,11); z2=(3.5,14); z3=(4,12); z4=(0.8,0); 1272 | z5=(6.5,14); z6=(7,12); z7=(3.8,0); 1273 | z8=(9.5,14); z9=(10,12); z10=(7,1); 1274 | add_char("M_", 15, [ 1275 | _draw2([(z1, sklon2),1 ,(z2,right),1,(z3,sklon1),1,(z4,sklon1)]), 1276 | _draw2([(z3,-sklon1),1.5,(z5,right),1,(z6,sklon1),1,(z7,sklon1)]), 1277 | _draw2([(z6,-sklon1),1.5,(z8,right),1,(z9,sklon1),1,(z10,sklon1)]), 1278 | shift(dotah, (z10[0],0)) 1279 | ]) 1280 | 1281 | #beginchar("N", 12u#, 14u#, 0); 1282 | # z1=(0.5,11); z2=(3.5,14); z3=(4,12); z4=(0.8,0); 1283 | # z5=(6.5,14); z6=(7,12); z7=(4,1); 1284 | # draw z1{sklon2}..z2{right}..z3{sklon1}..{sklon1}z4; 1285 | # draw z3{-sklon1}..tension1.5..z5{right}..z6{sklon1}..{sklon1}z7; 1286 | # dotah shifted (x7,0); 1287 | #endchar; 1288 | z1=(0.5,11); z2=(3.5,14); z3=(4,12); z4=(0.8,0); 1289 | z5=(6.5,14); z6=(7,12); z7=(4,1); 1290 | add_char("N_", 12, [ 1291 | _draw2([(z1, sklon2),1 ,(z2,right),1,(z3,sklon1),1,(z4,sklon1)]), 1292 | _draw2([(z3,-sklon1),1.5,(z5,right),1,(z6,sklon1),1,(z7,sklon1)]), 1293 | shift(dotah, (z7[0],0)) 1294 | ]) 1295 | add_char("N_caron", 12, [ 1296 | _draw2([(z1, sklon2),1 ,(z2,right),1,(z3,sklon1),1,(z4,sklon1)]), 1297 | _draw2([(z3,-sklon1),1.5,(z5,right),1,(z6,sklon1),1,(z7,sklon1)]), 1298 | shift(dotah, (z7[0],0)), 1299 | shift(hacek, (5,7)) 1300 | ]) 1301 | 1302 | #beginchar("O", 5u#, 14u#, 0); charic := 2u#; 1303 | # z0=(0,6); z1=(6,14); z2=(1,0); z3=(10,14); 1304 | # z1p=(4.5,13.9); z2p=(5.5,13); z1d=(6.5,13); 1305 | # draw z1{left}..z1p..tension1.5and1..z0{sklon1}..tension1.5.. 1306 | # z2{right}..tension2..z1d..z1{left}..z2p{down}..{sklon2}z3; 1307 | #endchar; 1308 | z0=(0,6); z1=(6,14); z2=(1,0); z3=(10,14); 1309 | z1p=(4.5,13.9); z2p=(5.5,13); z1d=(6.5,13); 1310 | z1pt=(-3,-1); z1dt=(0,1) 1311 | add_char("O_", 5, [ 1312 | _draw2([(z1,left),1,(z1p,z1pt),1.25,(z0,sklon1),1.5, 1313 | (z2,right),2,(z1d,z1dt),1,(z1,left),1,(z2p,down),1,(z3,sklon2)]), 1314 | ]) 1315 | add_char("O_acute", 5, [ 1316 | _draw2([(z1,left),1,(z1p,z1pt),1.25,(z0,sklon1),1.5, 1317 | (z2,right),2,(z1d,z1dt),1,(z1,left),1,(z2p,down),1,(z3,sklon2)]), 1318 | shift(capcarka, (6,0)) 1319 | ]) 1320 | add_char("O_circumflex", 5, [ 1321 | _draw2([(z1,left),1,(z1p,z1pt),1.25,(z0,sklon1),1.5, 1322 | (z2,right),2,(z1d,z1dt),1,(z1,left),1,(z2p,down),1,(z3,sklon2)]), 1323 | shift(vokan, (3.6,7)) 1324 | ]) 1325 | 1326 | #beginchar("P", 4u#, 14u#, 0); charic := 5u#; 1327 | # z0=(0,6); z1=(8,14); z2=(1,0); z2p=(3,3); 1328 | # z3=(0,4); z4=(5,8); 1329 | # draw z1{left}..z2p{sklon1}..z2{left}..z0{-sklon1}.. 1330 | # z1{right}..{left}z4; 1331 | #endchar; 1332 | z0=(0,6); z1=(8,14); z2=(1,0); z2p=(3,3); 1333 | z3=(0,4); z4=(5,8); 1334 | add_char("P_", 4, [ 1335 | _draw2([(z1,left),1,(z2p,sklon1),1,(z2,left),1,(z0,-sklon1),1, 1336 | (z1,right),1,(z4,left)]), 1337 | ]) 1338 | 1339 | #beginchar("Q", 10.9u#, 14u#, 7u#); 1340 | # z0=(0,6); z1=(5,12.5); z2=(x1+.3,11); z3=(x1+.1,14); 1341 | # z4=(1,0); z5=(5,7); 1342 | # z6=(3,-.5); z7-z6 = whatever*(z5-z6); y7=-7; 1343 | # z8=(x6+7.9,6); 1344 | # draw z1{sklon1}..z2{right}..tension1.5..z3{left}..tension2.. 1345 | # z0{sklon1}..z4{right}..tension1.5.. 1346 | # {-sklon1}z5{sklon1}..z6{sklon1}..{sklon1}z7; 1347 | # draw z6{-sklon1}..tension2..{sklon2}z8; 1348 | #endchar; 1349 | z0=(0,6); z1=(5,12.5); z2=(z1[0]+.3,11); z3=(z1[0]+.1,14); 1350 | z4=(1,0); z5=(5,7); 1351 | z6=(3,-.5); z7 = whatever_y(z6, array(z5)-array(z6), -7); 1352 | z8=(z6[0]+7.9,6); 1353 | add_char("Q_", 10.9, [ 1354 | _draw2([(z1,sklon1),1,(z2,right),1.5,(z3,left),2, 1355 | (z0,sklon1),1,(z4,right),1.5, 1356 | (-sklon1,z5,sklon1),1,(z6,sklon1),1,(z7,sklon1)]), 1357 | _draw2([(z6,-sklon1),2,(z8,sklon2)]) 1358 | ]) 1359 | 1360 | #beginchar("R", 14u#, 14u#, 0); 1361 | # z0=(0,6); z1=(8,14); z2=(1,0); z2p=(3,3); 1362 | # z3=(0,4); z4=(6,8); z4l=(x4-1,y4); 1363 | # z10=(8,0); z11=(14,6); 1364 | # draw z1{left}..z2p{sklon1}..z2{left}..z0{-sklon1}.. 1365 | # z1{right}..{dir215}z4..z4l{up}..z4{dir-35}.. 1366 | # tension1.5..z10{right}..tension3..{sklon2}z11; 1367 | #endchar; 1368 | z0=(0,6); z1=(8,14); z2=(1,0); z2p=(3,3); 1369 | z3=(0,4); z4=(6,8); z4l=(z4[0]-1,z4[1]); 1370 | z10=(8,0); z11=(14,6); 1371 | add_char("R_", 14, [ 1372 | _draw2([(z1,left),1,(z2p,sklon1),1,(z2,left),1,(z0,-sklon1),1, 1373 | (z1,right),1,(z4,dir_(215)),1,(z4l,up),1,(z4,dir_(-35)), 1374 | 1.5,(z10,right),3,(z11,sklon2)]), 1375 | ]) 1376 | add_char("R_caron", 14, [ 1377 | _draw2([(z1,left),1,(z2p,sklon1),1,(z2,left),1,(z0,-sklon1),1, 1378 | (z1,right),1,(z4,dir_(215)),1,(z4l,up),1,(z4,dir_(-35)), 1379 | 1.5,(z10,right),3,(z11,sklon2)]), 1380 | shift(hacek, (7,6)) 1381 | ]) 1382 | add_char("R_acute", 14, [ 1383 | _draw2([(z1,left),1,(z2p,sklon1),1,(z2,left),1,(z0,-sklon1),1, 1384 | (z1,right),1,(z4,dir_(215)),1,(z4l,up),1,(z4,dir_(-35)), 1385 | 1.5,(z10,right),3,(z11,sklon2)]), 1386 | shift(capcarka, (8,0)) 1387 | ]) 1388 | 1389 | #beginchar("S", 6u#, 14u#, 0); charic := 3u#; 1390 | # z1=(4,14); z2=(6,9); z3=(9,14); z4=(7,12); 1391 | # z5=(4.2,2); z6=(x5-2.2,0); z7=(x6-1.5,3); 1392 | # draw z1..z2{right}..tension1.7..z3{left}..z4{sklon1}..{sklon1}z5.. 1393 | # z6{left}..{up}z7; 1394 | #endchar; 1395 | z1=(4,14); z2=(6,9); z3=(9,14); z4=(7,12); 1396 | z5=(4.2,2); z6=(z5[0]-2.2,0); z7=(z6[0]-1.5,3); 1397 | z1t=(-1,-1) 1398 | add_char("S_", 6, [ 1399 | _draw2([(z1,z1t),1,(z2,right),1.7,(z3,left),1,(z4,sklon1),1,(z5,sklon1),1, 1400 | (z6,left),1,(z7,up)]), 1401 | ]) 1402 | add_char("S_caron", 6, [ 1403 | _draw2([(z1,z1t),1,(z2,right),1.7,(z3,left),1,(z4,sklon1),1,(z5,sklon1),1, 1404 | (z6,left),1,(z7,up)]), 1405 | shift(hacek, (7,6)) 1406 | ]) 1407 | 1408 | #beginchar("T", 5u#, 14u#, 0); charic := 7u#; 1409 | # z1=(4,12.5); z2=(3,10); z3=(2.3,12.5); z4=(4,14); 1410 | # z5=(7,13.5); z6=(12,14); 1411 | # z7=(4,4); z8=(1,0); z9=(0,3); 1412 | # draw z1{sklon1}..z2..z3{-sklon1}..z4{right}..z5..{right}z6; 1413 | # draw z5{-sklon2}..z7{sklon1}..z8{left}..{-sklon1}z9; 1414 | #endchar; 1415 | z1=(4,12.5); z2=(3,10); z3=(2.3,12.5); z4=(4,14); 1416 | z5=(7,13.5); z6=(12,14); 1417 | z7=(4,4); z8=(1,0); z9=(0,3); 1418 | z2t=(-1,0); z5t=(4,-1); 1419 | add_char("T_", 5, [ 1420 | _draw2([(z1,sklon1),1,(z2,z2t),1,(z3,-sklon1),1,(z4,right),1,(z5,z5t),1, 1421 | (z6,right)]), 1422 | _draw2([(z5,-sklon2),1,(z7,sklon1),1,(z8,left),1,(z9,-sklon1)]) 1423 | ]) 1424 | add_char("T_caron", 5, [ 1425 | _draw2([(z1,sklon1),1,(z2,z2t),1,(z3,-sklon1),1,(z4,right),1,(z5,z5t),1, 1426 | (z6,right)]), 1427 | _draw2([(z5,-sklon2),1,(z7,sklon1),1,(z8,left),1,(z9,-sklon1)]), 1428 | shift(hacek, (7,6)) 1429 | ]) 1430 | 1431 | #beginchar("U", 11.7u#, 14u#, 0); 1432 | # z1=(-.5,11); z2=(2.5,14); z3=(3,12); z4=(0,1); 1433 | # z5=(0.5,0); z6=(7,14); z7=(3.7,1); 1434 | # draw z1{sklon2}..z2{right}..z3{sklon1}..{sklon1}z4.. 1435 | # z5{right}..tension1.7..{-sklon1}z6--z7; 1436 | # dotah shifted (x7,0); 1437 | #endchar; 1438 | z1=(-.5,11); z2=(2.5,14); z3=(3,12); z4=(0,1); 1439 | z5=(0.5,0); z6=(7,14); z7=(3.7,1); 1440 | add_char("U_", 11.7, [ 1441 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1),1, 1442 | (z5,right),1.7,(z6,-sklon1),None,(z7,None)]), 1443 | shift(dotah, (z7[0],0)) 1444 | ]) 1445 | add_char("U_acute", 11.7, [ 1446 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1),1, 1447 | (z5,right),1.7,(z6,-sklon1),None,(z7,None)]), 1448 | shift(dotah, (z7[0],0)), 1449 | shift(capcarka, (5.5,0)) 1450 | ]) 1451 | add_char("U_ring", 11.7, [ 1452 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1),1, 1453 | (z5,right),1.7,(z6,-sklon1),None,(z7,None)]), 1454 | shift(dotah, (z7[0],0)), 1455 | shift(krouzek, (5.5,6)) 1456 | ]) 1457 | 1458 | #beginchar("V", 5.5u#, 14u#, 0); charic := 5u#; 1459 | # z1=(-.5,11); z2=(2.5,14); z3=(3,12); z4=(0,1); 1460 | # z5=(0.5,0); z9=(6.5,14); z9d=(x9+.5,y9-1); z9p=(x9-.5,y9-1); 1461 | # z10=(10.5,14); 1462 | # draw z1{sklon2}..z2{right}..z3{sklon1}..{sklon1}z4.. 1463 | # z5{right}..tension1.7..{-sklon1}z9d.. 1464 | # z9{left}..z9p{down}..{sklon2}z10; 1465 | #endchar; 1466 | z1=(-.5,11); z2=(2.5,14); z3=(3,12); z4=(0,1); 1467 | z5=(0.5,0); z9=(6.5,14); z9d=(z9[0]+.5,z9[1]-1); z9p=(z9[0]-.5,z9[1]-1); 1468 | z10=(10.5,14); 1469 | add_char("V_", 5.5, [ 1470 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1),1, 1471 | (z5,right),1.7,(z9d,-sklon1),1, 1472 | (z9,left),1,(z9p,down),1,(z10,sklon2)]), 1473 | ]) 1474 | 1475 | #beginchar("W", 8.3u#, 14u#, 0); charic := 5u#; 1476 | # z1=(-.5,11); z2=(2.5,14); z3=(3,12); 1477 | # z4=(0,1); z5=(0.5,0); z6=(7,14); 1478 | # z7=(3.8,1); z8=(4.3,0); 1479 | # z9=(10.3,14); z9d=(x9+.5,y9-1); z9p=(x9-.5,y9-1); 1480 | # z10=(14.7,14); 1481 | # draw z1{sklon2}..z2{right}..z3{sklon1}..{sklon1}z4.. 1482 | # z5{right}..tension1.7..{-sklon1}z6{sklon1}.. 1483 | # {sklon1}z7..z8{right}..tension1.7..{-sklon1}z9d.. 1484 | # z9{left}..z9p{down}..{sklon2}z10; 1485 | #endchar; 1486 | z1=(-.5,11); z2=(2.5,14); z3=(3,12); 1487 | z4=(0,1); z5=(0.5,0); z6=(7,14); 1488 | z7=(3.8,1); z8=(4.3,0); 1489 | z9=(10.3,14); z9d=(z9[0]+.5,z9[1]-1); z9p=(z9[0]-.5,z9[1]-1); 1490 | z10=(14.7,14); 1491 | add_char("W_", 8.3, [ 1492 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1),1, 1493 | (z5,right),1.7,(-sklon1,z6,sklon1),1, 1494 | (z7,sklon1),1,(z8,right),1.7,(z9d,-sklon1),1, 1495 | (z9,left),1,(z9p,down),1,(z10,sklon2)]), 1496 | ]) 1497 | 1498 | #beginchar("X", 15.1u#, 14u#, 0); 1499 | # z1=(2.5,11); z2=(5.5,14); z3=(7,12); z4=(7.1,1); 1500 | # z7=(14,11); z8=(12,14); z10=(7,8); z9=(1,0); z6=(-.5,3); 1501 | # draw z1{sklon2}..z2{right}..z3--z4; 1502 | # draw z7{dir110}..z8{left}..tension2..z10..tension1.5..{left}z9..{up}z6; 1503 | # dotah shifted (x4,0); 1504 | #endchar; 1505 | z1=(2.5,11); z2=(5.5,14); z3=(7,12); z4=(7.1,1); 1506 | z7=(14,11); z8=(12,14); z10=(7,8); z9=(1,0); z6=(-.5,3); 1507 | z3t=array(z4)-array(z3); z10t=(-1,-2) 1508 | add_char("X_", 15.1, [ 1509 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,z3t),None,(z4,None)]), 1510 | _draw2([(z7,dir_(110)),1,(z8,left),2,(z10,z10t),1.5,(z9,left),1,(z6,up)]), 1511 | shift(dotah, (z4[0],0)) 1512 | ]) 1513 | 1514 | 1515 | #beginchar("Y", 10.7u#, 14u#, 7u#); 1516 | # z1=(-.5,11); z2=(2.5,14); z3=(3,12); z4=(0,1); 1517 | # z5=(0.5,0); z6=(7,14); z7=(5.2,7); 1518 | # draw z1{sklon2}..z2{right}..z3{sklon1}..{sklon1}z4.. 1519 | # z5{right}..tension1.7..{-sklon1}z6--z7; 1520 | # smycka shifted (x7, 0); 1521 | #endchar; 1522 | z1=(-.5,11); z2=(2.5,14); z3=(3,12); z4=(0,1); 1523 | z5=(0.5,0); z6=(7,14); z7=(5.2,7); 1524 | add_char("Y_", 10.7, [ 1525 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1),1, 1526 | (z5,right),1.7,(z6,-sklon1),None,(z7,None)]), 1527 | shift(smycka, (z7[0],0)) 1528 | ]) 1529 | add_char("Y_acute", 10.7, [ 1530 | _draw2([(z1,sklon2),1,(z2,right),1,(z3,sklon1),1,(z4,sklon1),1, 1531 | (z5,right),1.7,(z6,-sklon1),None,(z7,None)]), 1532 | shift(smycka, (z7[0],0)), 1533 | shift(capcarka, (5.5,0)) 1534 | ]) 1535 | 1536 | #beginchar("Z", 12u#, 14u#, 0); 1537 | # z1=(1,12); z2=(4,14); z3=(7.5,13); z4=(9,14); z4p=(x4+1,y4-.5); 1538 | # z5=(2,1); z5d=(.5,0); z5p=(-.5,.8); z6=(6,0); z7=(12,6); 1539 | # draw z1..z2{right}..z3..z4p{up}..z4{left}..z3.. 1540 | # z5..z5d{left}..z5p{up}..z5..z6{right}..tension2..{sklon2}z7; 1541 | #endchar; 1542 | z1=(1,12); z2=(4,14); z3=(7.5,13); z4=(9,14); z4p=(z4[0]+1,z4[1]-.5); 1543 | z5=(2,1); z5d=(.5,0); z5p=(-.5,.8); z6=(6,0); z7=(12,6); 1544 | z1t=(1,1); z3t=(1,-1); z3t2=(-1,-2); z5t=(-1,-2); z5t2=(2,-1) 1545 | add_char("Z_", 12, [ 1546 | _draw2([(z1,z1t),1,(z2,right),1,(z3,z3t),1,(z4p,up),1,(z4,left),1,(z3,z3t2),1, 1547 | (z5,z5t),1,(z5d,left),1,(z5p,up),1,(z5,z5t2),1,(z6,right),2,(z7,sklon2)]), 1548 | ]) 1549 | add_char("Z_caron", 12, [ 1550 | _draw2([(z1,z1t),1,(z2,right),1,(z3,z3t),1,(z4p,up),1,(z4,left),1,(z3,z3t2),1, 1551 | (z5,z5t),1,(z5d,left),1,(z5p,up),1,(z5,z5t2),1,(z6,right),2,(z7,sklon2)]), 1552 | shift(hacek, (6,6)) 1553 | ]) 1554 | 1555 | ################################################################################ 1556 | # Digits 1557 | 1558 | #beginchar("1", 8u#, 14u#, 0); 1559 | # z1=(1.5,9); z2=(5.5,14); z3=(2.5,0); 1560 | # draw z1..{dir60}z2--z3; 1561 | #endchar; 1562 | z1=(1.5,9); z2=(5.5,14); z3=(2.5,0); 1563 | z1t=(1,1) 1564 | add_char("one", 8, [ 1565 | _draw2([(z1,z1t),1,(z2,dir_(60)),None,(z3,None)]), 1566 | ]) 1567 | 1568 | #beginchar("2", 8u#, 14u#, 0); 1569 | # z1=(1.5,11); z2=(4,14); z3=(6,11); z4=(0,0); z5=(5,0); 1570 | # draw z1..z2{right}..z3{-dir80}..{-dir65}z4--z5; 1571 | #endchar; 1572 | z1=(1.5,11); z2=(4,14); z3=(6,11); z4=(0,0); z5=(5,0); 1573 | z1t=(0,1) 1574 | add_char("two", 8, [ 1575 | _draw2([(z1,z1t),1,(z2,right),1,(z3,-dir_(80)),1, 1576 | (z4,-dir_(65)),None,(z5,None)]), 1577 | ]) 1578 | 1579 | #beginchar("3", 8u#, 14u#, 0); 1580 | # z1=(1.5,11); z2=(4,14); z3=(6,11); z4=(3,8); z5=(2,0); z6=(-.5,3); 1581 | # draw z1..z2{right}..z3{-dir80}..z4&z4..tension1.5..z5{left}..z6{up}; 1582 | #endchar; 1583 | z1=(1.5,11); z2=(4,14); z3=(6,11); z4=(3,8); z5=(2,0); z6=(-.5,3); 1584 | z1t=(0,1) 1585 | add_char("three", 8, [ 1586 | _draw2([(z1,z1t),1,(z2,right),1,(z3,-dir_(80)),1,(z4,(-1,0))]), 1587 | _draw2([(z4,(4,-1)),1.5,(z5,left),1,(z6,up)]), 1588 | ]) 1589 | 1590 | #beginchar("4", 8u#, 14u#, 0); 1591 | # z1=(5,14); z2=(0,6); z3=(6,6); z4=(4.5,9); z5=(2.5,0); 1592 | # draw z1--z2--z3; 1593 | # draw z4--z5; 1594 | #endchar; 1595 | z1=(5,14); z2=(0,6); z3=(6,6); z4=(4.5,9); z5=(2.5,0); 1596 | add_char("four", 8, [ 1597 | _draw2([(z1,None),None,(z2,None),None,(z3,None)]), 1598 | _draw2([(z4,None),None,(z5,None)]), 1599 | ]) 1600 | 1601 | #beginchar("5", 8u#, 14u#, 0); 1602 | # z1=(6,14); z2=(2.5,14); z3=(1,8); z4=(4,9); z5=(2,0); z6=(-.5,3); 1603 | # draw z1--z2--z3&z3..z4..tension1.5..z5{left}..z6{up}; 1604 | #endchar; 1605 | z1=(6,14); z2=(2.5,14); z3=(1,8); z4=(4,9); z5=(2,0); z6=(-.5,3); 1606 | z3t=array(z2)-array(z3); z4t=dir_(-42) 1607 | add_char("five", 8, [ 1608 | _draw2([(z1,None),None,(z2,None),None,(z3,None)]), 1609 | _draw2([(z3,z3t),1,(z4,z4t),1.5,(z5,left),1,(z6,up)]), 1610 | ]) 1611 | 1612 | #beginchar("6", 8u#, 14u#, 0); 1613 | # z1=(6,14); z3=(.5,5); z4=(4,8); z5=(2,0); z6=(-.5,3); 1614 | # draw z1{-dir35}..z3{sklon1}&z3{-sklon1}..z4..tension1.5..z5{left}.. 1615 | # z3{-sklon1}; 1616 | #endchar; 1617 | z1=(6,14); z3=(.5,5); z4=(4,8); z5=(2,0); z6=(-.5,3); 1618 | z4t=dir_(-38) 1619 | add_char("six", 8, [ 1620 | _draw2([(z1,-dir_(35)),1,(z3,sklon1)]), 1621 | _draw2([(z3,-sklon1),1,(z4,z4t),1.5,(z5,left),1,(z3,-sklon1)]), 1622 | ]) 1623 | 1624 | #beginchar("7", 8u#, 14u#, 0); 1625 | # z1=(0.5,14); z2=(6,14); z3=(0,0); z4=(1.5,7); z5=(4.5,7); 1626 | # draw z1--z2--z3; 1627 | # draw z4--z5; 1628 | #endchar; 1629 | z1=(0.5,14); z2=(6,14); z3=(0,0); z4=(1.5,7); z5=(4.5,7); 1630 | add_char("seven", 8, [ 1631 | _draw2([(z1,None),None,(z2,None),None,(z3,None)]), 1632 | _draw2([(z4,None),None,(z5,None)]), 1633 | ]) 1634 | 1635 | #beginchar("8", 8u#, 14u#, 0); 1636 | # z1=(4,14); z2=(3.2,8); z3=(2,0); 1637 | # draw z1{left}..z2..z3{left}..z2..{left}z1; 1638 | #endchar; 1639 | z1=(4,14); z2=(3.2,8); z3=(2,0); 1640 | z2t=dir_(-57.8); z2t2=dir_(-326) 1641 | add_char("eight", 8, [ 1642 | _draw2([(z1,left),1,(z2,z2t),1,(z3,left),1,(z2,z2t2),1,(z1,left)]), 1643 | ]) 1644 | 1645 | #beginchar("9", 8u#, 14u#, 0); 1646 | # z0=(2,13); z1=(6,14); z2=(1,7); z3=(2.5,0); 1647 | # z1p=(4,13.9); 1648 | # draw z1{left}..z1p..z0{-sklon2}..tension1.5.. 1649 | # z2{right}..tension1.2..{-sklon1}z1{sklon1}..z3{sklon1}; 1650 | #endchar; 1651 | z0=(2,13); z1=(6,14); z2=(1,7); z3=(2.5,0); 1652 | z1p=(4,13.9);z1pt=dir_(-168) 1653 | add_char("nine", 8, [ 1654 | _draw2([(z1,left),1,(z1p,z1pt),1,(z0,-sklon2),1.5, 1655 | (z2,right),1.2,(-sklon1,z1,sklon1),1,(z3,sklon1)]), 1656 | ]) 1657 | 1658 | #beginchar("0", 8u#, 14u#, 0); 1659 | # z1=(4,14); z3=(1,0); 1660 | # draw z1{left}..tension2.9..z3{right}..tension2.9..{left}z1; 1661 | #endchar; 1662 | z1=(4,14); z3=(1,0); 1663 | add_char("zero", 8, [ 1664 | _draw2([(z1,left),2.9,(z3,right),2.9,(z1,left)]), 1665 | ]) 1666 | 1667 | ################################################################################ 1668 | # Others 1669 | 1670 | # .notdef 1671 | z1=(0.5,14); z2=(15,14); z3=(15,0); z4=(0.5,0); 1672 | add_char("_notdef", 15, [ 1673 | _draw2([(z1,None),None,(z2,None),None,(z3,None),None,(z4,None),None, 1674 | (z1,None)]), 1675 | _draw2([(z1,None),None,(z3,None)]), 1676 | _draw2([(z2,None),None,(z4,None)]), 1677 | ]) 1678 | 1679 | # space 1680 | add_char("space", 115/40, []) 1681 | 1682 | # subs_token 1683 | add_char("subs_token", 10/40, []) 1684 | 1685 | #beginchar("+", 8u#, 9u#, 0); 1686 | # z1=(1,7); z2=(6,7); z3=(3.3,4.5); z4=(3.7,9.5); 1687 | # draw z1--z2; 1688 | # draw z3--z4; 1689 | #endchar; 1690 | z1=(1,7); z2=(6,7); z3=(3.3,4.5); z4=(3.7,9.5); 1691 | add_char("plus", 8, [ 1692 | _draw2([(z1,None),None,(z2,None)]), 1693 | _draw2([(z3,None),None,(z4,None)]), 1694 | ]) 1695 | 1696 | #beginchar(minus, 8u#, 7u#, 0); 1697 | # z1=(1,7); z2=(6,7); 1698 | # draw z1--z2; 1699 | #endchar; 1700 | z1=(1,7); z2=(6,7); 1701 | add_char("minus", 8, [ 1702 | _draw2([(z1,None),None,(z2,None)]), 1703 | ]) 1704 | 1705 | #beginchar(times, 8u#, 9u#, 0); 1706 | # z1=(1.7,9); z2=(5.7,9); z3=(1.3,5); z4=(5.3,5); 1707 | # draw z1--z4; 1708 | # draw z2--z3; 1709 | #endchar; 1710 | z1=(1.7,9); z2=(5.7,9); z3=(1.3,5); z4=(5.3,5); 1711 | add_char("multiply", 8, [ 1712 | _draw2([(z1,None),None,(z4,None)]), 1713 | _draw2([(z2,None),None,(z3,None)]), 1714 | ]) 1715 | 1716 | #beginchar("*", 8u#, 9u#, 0); 1717 | # z1=(1.7,10); z2=(5.7,10); z3=(1.3,4); z4=(5.3,4); 1718 | # draw z1--z4; 1719 | # draw z2--z3; 1720 | # draw (0,7)--(7,7); 1721 | #endchar; 1722 | z1=(1.7,10); z2=(5.7,10); z3=(1.3,4); z4=(5.3,4); 1723 | add_char("asterisk", 8, [ 1724 | _draw2([(z1,None),None,(z4,None)]), 1725 | _draw2([(z2,None),None,(z3,None)]), 1726 | _draw2([((0,7),None),None,((7,7),None)]), 1727 | ]) 1728 | 1729 | #beginchar("=", 8u#, 9u#, 0); 1730 | # z1=(1,6); z2=(6,6); z3=(1.2,8); z4=(6.2,8); 1731 | # draw z1--z2; 1732 | # draw z3--z4; 1733 | #endchar; 1734 | z1=(1,6); z2=(6,6); z3=(1.2,8); z4=(6.2,8); 1735 | add_char("equal", 8, [ 1736 | _draw2([(z1,None),None,(z2,None)]), 1737 | _draw2([(z3,None),None,(z4,None)]), 1738 | ]) 1739 | 1740 | #beginchar(slash, 8u#, 14u#, 0); 1741 | # z1=(0,0); z2=(9,14); 1742 | # draw z1--z2; 1743 | #endchar; 1744 | z1=(0,0); z2=(9,14); 1745 | add_char("slash", 8, [ 1746 | _draw2([(z1,None),None,(z2,None)]), 1747 | ]) 1748 | 1749 | #beginchar(backslash, 6u#, 14u#, 0); 1750 | # z1=(0,14); z2=(6,0); 1751 | # draw z1--z2; 1752 | #endchar; 1753 | z1=(0,14); z2=(6,0); 1754 | add_char("backslash", 6, [ 1755 | _draw2([(z1,None),None,(z2,None)]), 1756 | ]) 1757 | 1758 | #beginchar("<", 8u#, 14u#, 0); 1759 | # z1=(1,7); z2=(7,10); z3=(6,4); 1760 | # draw z3--z1--z2; 1761 | #endchar; 1762 | z1=(1,7); z2=(7,10); z3=(6,4); 1763 | add_char("less", 8, [ 1764 | _draw2([(z3,None),None,(z1,None),None,(z2,None)]), 1765 | ]) 1766 | 1767 | #beginchar(">", 8u#, 14u#, 0); 1768 | # z1=(7,7); z2=(2,10); z3=(1,4); 1769 | # draw z3--z1--z2; 1770 | #endchar; 1771 | z1=(7,7); z2=(2,10); z3=(1,4); 1772 | add_char("greater", 8, [ 1773 | _draw2([(z3,None),None,(z1,None),None,(z2,None)]), 1774 | ]) 1775 | 1776 | #beginchar("@", 9u#, 9u#, 2u#); 1777 | # z0=(4,6); z1=(7,7); z2=(3,0); z3=(5.4,1); 1778 | # z1p=(5.5,6.9); 1779 | # z4=(6,0); z5=(9,4); z6=(7,9); z7=(1,0); z8=(7,-1); 1780 | # draw z1{left}..z1p..z0{-sklon2}..tension1.5.. 1781 | # z2{right}..tension1.2..{-sklon1}z1{sklon1}..z3{sklon1}.. 1782 | # z4{right}..z5..z6..z7{dir-60}..z8; 1783 | #endchar; 1784 | z0=(4,6); z1=(7,7); z2=(3,0); z3=(5.4,1); 1785 | z1p=(5.5,6.9); 1786 | z4=(6,0); z5=(9,4); z6=(7,9); z7=(1,0); z8=(7,-1); 1787 | z1pt=(-4,-1); z5t=dir_(-285); z6t=dir_(-190); z8t=(1,1) 1788 | add_char("at", 9, [ 1789 | _draw2([(z1,left),1,(z1p,z1pt),1,(z0,-sklon2),1.5, 1790 | (z2,right),1.2,(-sklon1,z1,sklon1),1,(z3,sklon1),1, 1791 | (z4,right),1,(z5,z5t),1,(z6,z6t),1,(z7,dir_(-60)),1,(z8,z8t)]), 1792 | ]) 1793 | 1794 | #beginchar("(", 8u#, 16u#, 2u#); 1795 | # z1=(7,16); z2=(2,7); z3=(5,-2); 1796 | # draw z1..z2..z3; 1797 | #endchar; 1798 | z1=(7,16); z2=(2,7); z3=(5,-2); 1799 | z1t=(-1,-1); z2t=(0,-1); z3t=(1,-1) 1800 | add_char("parenleft", 8, [ 1801 | _draw2([(z1,z1t),1,(z2,z2t),1,(z3,z3t)]), 1802 | ]) 1803 | 1804 | #beginchar(")", 8u#, 16u#, 2u#); 1805 | # z1=(3,16); z2=(6,7); z3=(1,-2); 1806 | # draw z1..z2..z3; 1807 | #endchar; 1808 | z1=(3,16); z2=(6,7); z3=(1,-2); 1809 | z1t=(1,-1); z2t=(0,-1); z3t=(-1,-1) 1810 | add_char("parenright", 8, [ 1811 | _draw2([(z1,z1t),1,(z2,z2t),1,(z3,z3t)]), 1812 | ]) 1813 | 1814 | #beginchar("[", 8u#, 14u#, 2u#); 1815 | # z1=(7,14); z1a=(4,14); z2a=(2,0); z2=(5,0); 1816 | # draw z1--z1a--z2a--z2; 1817 | #endchar; 1818 | z1=(7,14); z1a=(4,14); z2a=(2,0); z2=(5,0); 1819 | add_char("bracketleft", 8, [ 1820 | _draw2([(z1,None),None,(z1a,None),None,(z2a,None),None,(z2,None)]), 1821 | ]) 1822 | 1823 | #beginchar("]", 8u#, 14u#, 2u#); 1824 | # z1=(6,14); z1a=(3,14); z2a=(1,0); z2=(4,0); 1825 | # draw z1a--z1--z2--z2a; 1826 | #endchar; 1827 | z1=(6,14); z1a=(3,14); z2a=(1,0); z2=(4,0); 1828 | add_char("bracketright", 8, [ 1829 | _draw2([(z1a,None),None,(z1,None),None,(z2,None),None,(z2a,None)]), 1830 | ]) 1831 | 1832 | #beginchar("{", 8u#, 14u#, 0); 1833 | # z1=(7,14); z7=(5.5,0); z1a=(5,14); z2a=(3,0); 1834 | # z2-z1a = whatever*(z2a-z1a); y2=12; 1835 | # z3-z1a = whatever*(z2a-z1a); y3=9; 1836 | # z4 = (2,7); 1837 | # z5-z1a = whatever*(z2a-z1a); y5=5; 1838 | # z6-z1a = whatever*(z2a-z1a); y6=2; 1839 | # draw z1{left}..z2..z3..z4&z4..z5..z6..{right}z7; 1840 | #endchar; 1841 | z1=(7,14); z7=(5.5,0); z1a=(5,14); z2a=(3,0); 1842 | z2 = whatever_y(z1a, array(z2a)-array(z1a), 12) 1843 | z3 = whatever_y(z1a, array(z2a)-array(z1a), 9) 1844 | z4 = (2,7); 1845 | z5 = whatever_y(z1a, array(z2a)-array(z1a), 5) 1846 | z6 = whatever_y(z1a, array(z2a)-array(z1a), 2) 1847 | z2t=sklon1;z3t=sklon1;z5t=sklon1;z6t=sklon1 1848 | add_char("braceleft", 8, [ 1849 | _draw2([(z1,left),1,(z2,z2t),1,(z3,z3t),1,(z4,left)]), 1850 | _draw2([(z4,right),1,(z5,z5t),1,(z6,z6t),1,(z7,right)]), 1851 | ]) 1852 | 1853 | #beginchar("}", 8u#, 14u#, 0); 1854 | # z1=(2.5,14); z7=(1,0); z1a=(5,14); z2a=(3,0); 1855 | # z2-z1a = whatever*(z2a-z1a); y2=12; 1856 | # z3-z1a = whatever*(z2a-z1a); y3=9; 1857 | # z4 = (7,7); 1858 | # z5-z1a = whatever*(z2a-z1a); y5=5; 1859 | # z6-z1a = whatever*(z2a-z1a); y6=2; 1860 | # draw z1{right}..z2..z3..z4&z4..z5..z6..{left}z7; 1861 | #endchar; 1862 | z1=(2.5,14); z7=(1,0); z1a=(5,14); z2a=(3,0); 1863 | z2 = whatever_y(z1a, array(z2a)-array(z1a), 12) 1864 | z3 = whatever_y(z1a, array(z2a)-array(z1a), 9) 1865 | z4 = (7,7); 1866 | z5 = whatever_y(z1a, array(z2a)-array(z1a), 5) 1867 | z6 = whatever_y(z1a, array(z2a)-array(z1a), 2) 1868 | z2t=sklon1;z3t=sklon1;z5t=sklon1;z6t=sklon1 1869 | add_char("braceright", 8, [ 1870 | _draw2([(z1,right),1,(z2,z2t),1,(z3,z3t),1,(z4,right)]), 1871 | _draw2([(z4,left),1,(z5,z5t),1,(z6,z6t),1,(z7,left)]), 1872 | ]) 1873 | 1874 | #beginchar(percent, 10u#, 14u#, 0); 1875 | # z1=(0,0); z2=(9,14); z3=(3,14); z4=(2,9); 1876 | # draw z1--z2; 1877 | # draw z3..tension2..z4..tension2..cycle; 1878 | # draw (z3..tension2..z4..tension2..cycle) shifted (4,-y4); 1879 | #endchar; 1880 | z1=(0,0); z2=(9,14); z3=(3,14); z4=(2,9); 1881 | add_char("percent", 10, [ 1882 | _draw2([(z1,None),None,(z2,None)]), 1883 | _draw2([(z3,right),2,(z4,left),2,(z3,right)]), 1884 | shift(_draw2([(z3,right),2,(z4,left),2,(z3,right)]), (4,-z4[1])), 1885 | ]) 1886 | 1887 | #beginchar(promile, 13u#, 14u#, 0); 1888 | # z1=(0,0); z2=(9,14); z3=(3,14); z4=(2,9); 1889 | # draw z1--z2; 1890 | # draw z3..tension2..z4..tension2..cycle; 1891 | # draw (z3..tension2..z4..tension2..cycle) shifted (4,-y4); 1892 | # draw (z3..tension2..z4..tension2..cycle) shifted (8,-y4); 1893 | #endchar; 1894 | z1=(0,0); z2=(9,14); z3=(3,14); z4=(2,9); 1895 | add_char("perthousand", 13, [ 1896 | _draw2([(z1,None),None,(z2,None)]), 1897 | _draw2([(z3,right),2,(z4,left),2,(z3,right)]), 1898 | shift(_draw2([(z3,right),2,(z4,left),2,(z3,right)]), (4,-z4[1])), 1899 | shift(_draw2([(z3,right),2,(z4,left),2,(z3,right)]), (8,-z4[1])), 1900 | ]) 1901 | 1902 | #beginchar("&", 7u#, 11u#, 0); 1903 | # z1=(5,0); z2=(3,7); z3=(4,11); z4=(0,1.5); z5=(1,0); z6=(7,7); 1904 | # draw z1..z2..z3{right}..z2..tension2..z4{sklon1}..z5{right}..tension2.. 1905 | # {sklon2}z6; 1906 | #endchar; 1907 | z1=(5,0); z2=(3,7); z3=(4,11); z4=(0,1.5); z5=(1,0); z6=(7,7); 1908 | z1t=dir_(-253); z2t=dir_(-254); z2t2=dir_(-120); 1909 | add_char("ampersand", 7, [ 1910 | _draw2([(z1,z1t),1,(z2,z2t),1,(z3,right),1,(z2,z2t2),2,(z4,sklon1),1, 1911 | (z5,right),2,(z6,sklon2)]), 1912 | ]) 1913 | 1914 | #beginchar("$", 8u#, 15u#, 1u#); 1915 | # z1=(8,10.5); z2=(4.5,14); z2a=(1,10.5); 1916 | # z3=(4,7); 1917 | # z4=(3.5,0); z4a=(7,3.5); z5=(0,3.5); 1918 | # draw z1..z2{left}..z2a..z3..z4a..z4{left}..z5; 1919 | # draw (2.5,-1)--(3.5,15); 1920 | # draw (4.5,-1)--(5.5,15); 1921 | #endchar; 1922 | z1=(8,10.5); z2=(4.5,14); z2a=(1,10.5); 1923 | z3=(4,7); 1924 | z4=(3.5,0); z4a=(7,3.5); z5=(0,3.5); 1925 | z1t=(0,1); z2at=(0,-1); z3t=dir_(-30); z4at=(0,-1); z5t=(0,1) 1926 | add_char("dollar", 8, [ 1927 | _draw2([(z1,z1t),1,(z2,left),1,(z2a,z2at),1,(z3,z3t),1,(z4a,z4at),1, 1928 | (z4,left),1,(z5,z5t)]), 1929 | _draw2([((2.5,-1),None),None,((3.5,15),None)]), 1930 | _draw2([((4.5,-1),None),None,((5.5,15),None)]), 1931 | ]) 1932 | 1933 | #beginchar("#", 11.5u#, 14u#, 0); 1934 | # z1=(0,0); z2=(4,14); z3=(10.5,0); 1935 | # draw (z1--z2) shifted (2,0); 1936 | # draw (z1--z2) shifted (6,0); 1937 | # draw (z1--z3) shifted (.5,5); 1938 | # draw (z1--z3) shifted (1.3,9); 1939 | #endchar; 1940 | z1=(0,0); z2=(4,14); z3=(10.5,0); 1941 | add_char("numbersign", 11.5, [ 1942 | shift(_draw2([(z1,None),None,(z2,None)]), (2,0)), 1943 | shift(_draw2([(z1,None),None,(z2,None)]), (6,0)), 1944 | shift(_draw2([(z1,None),None,(z3,None)]), (0.5,5)), 1945 | shift(_draw2([(z1,None),None,(z3,None)]), (1.3,9)), 1946 | ]) 1947 | 1948 | #beginchar("|", 2u#, 14u#, 0); 1949 | # z1=(0,0); z2=(2,14); 1950 | # draw (z1--z2) 1951 | #endchar; 1952 | z1=(0,0); z2=(2,14); 1953 | add_char("bar", 2, [ 1954 | _draw2([(z1,None),None,(z2,None)]), 1955 | ]) 1956 | 1957 | #beginchar("~", 8u#, 9u#, 0); 1958 | # z1=(0,6); z2=(3,8); z3=(5,6); z4=(8,8); 1959 | # draw z1..z2..z3..z4; 1960 | #endchar; 1961 | z1=(0,6); z2=(3,8); z3=(5,6); z4=(8,8); 1962 | z1t=(0,1); z2t=dir_(-27); z3t=dir_(-27); z4t=(0,1); 1963 | add_char("asciitilde", 8, [ 1964 | _draw2([(z1,z1t),1,(z2,z2t),1,(z3,z3t),1,(z4,z4t)]), 1965 | ]) 1966 | 1967 | #beginchar(inch, 4u#, 15u#, 0); 1968 | # draw (1.8,15)--(1.5,12); 1969 | # draw (3.8,15)--(3.5,12); 1970 | #endchar; 1971 | add_char("quotedbl.sc", 4, [ 1972 | _draw2([((1.8,15),None),None,((1.5,12),None)]), 1973 | _draw2([((3.8,15),None),None,((3.5,12),None)]), 1974 | ]) 1975 | 1976 | #beginchar("^", 6u#, 14u#, 0); 1977 | # draw (2,12)--(4,14)--(6,12); 1978 | #endchar; 1979 | add_char("asciicircum", 6, [ 1980 | _draw2([((2,12),None),None,((4,14),None),None,((6,12),None)]), 1981 | ]) 1982 | 1983 | #beginchar("_", 8u#, 0, 7u#); 1984 | # draw (0,-7)--(8,-7); 1985 | #endchar; 1986 | add_char("underscore", 8, [ 1987 | _draw2([((0,-7),None),None,((8,-7),None)]), 1988 | ]) 1989 | 1990 | 1991 | 1992 | ################################################################################ 1993 | # Punctuation 1994 | 1995 | #beginchar("-", 3u#, 7u#, 0); 1996 | # draw (0,4)--(3,4); 1997 | #endchar; 1998 | add_char("hyphen", 3, [ 1999 | _draw2([((0,4),None),None,((3,4),None)]), 2000 | ]) 2001 | 2002 | #beginchar(dash, 12u#, 7u#, 0); 2003 | # z1=(1,7); z2=(10,7); 2004 | # draw z1--z2; 2005 | #endchar; 2006 | # TODO: the font has emdash, twoemdash, threeemdash, endash, but none 2007 | # of them seem to work; but latex puts two and three hyphens instead. 2008 | # We generate the `letter_dash.svg`, but we do not copy it into glyphs. 2009 | add_char("dash", 12, [ 2010 | _draw2([((1,7),None),None,((10,7),None)]), 2011 | ]) 2012 | 2013 | #beginchar("!", 6u#, 14u#, 0); 2014 | # pickup pencircle scaled (dotkoef*thin); 2015 | # drawdot (2,0); 2016 | # pickup pencircle scaled thin; 2017 | # draw (2.6, 4)..(5,14); 2018 | #endchar; 2019 | add_char("exclam", 12, [ 2020 | shift(dot, (2,0)), 2021 | _draw2([((2.6,4),None),None,((5,14),None)]), 2022 | ]) 2023 | 2024 | #beginchar("?", 8u#, 14u#, 0); 2025 | # pickup pencircle scaled (dotkoef*thin); 2026 | # drawdot (4,0); 2027 | # pickup pencircle scaled thin; 2028 | # z1=(3,12); z2=(6,14); z3=(5,8.5); z4=(4.5,3); z5=(7,5); 2029 | # draw z1..z2{right}..z3..z4{right}..z5; 2030 | #endchar; 2031 | z1=(3,12); z2=(6,14); z3=(5,8.5); z4=(4.5,3); z5=(7,5); 2032 | z1t=up; z3t=(-1,-1); z5t=up 2033 | add_char("question", 8, [ 2034 | shift(dot, (4,0)), 2035 | _draw2([(z1,z1t),1,(z2,right),1,(z3,z3t),1,(z4,right),1,(z5,z5t)]), 2036 | ]) 2037 | 2038 | #beginchar(",", 3u#, 1u#, 0); 2039 | # draw (0,1)--(-1,-2); 2040 | #endchar; 2041 | add_char("comma", 3, [ 2042 | _draw2([((0,1),None),None,((-1,-2),None)]), 2043 | ]) 2044 | 2045 | #beginchar(".", 3u#, 1u#, 0); 2046 | # pickup pencircle scaled (dotkoef*thin); 2047 | # drawdot (0,0); 2048 | # pickup pencircle scaled thin; 2049 | #endchar; 2050 | add_char("period", 3, [ 2051 | shift(dot, (0,0)), 2052 | ]) 2053 | 2054 | #beginchar(":", 4u#, 7u#, 0); 2055 | # pickup pencircle scaled (dotkoef*thin); 2056 | # drawdot (1,0); drawdot (2,7); 2057 | # pickup pencircle scaled thin; 2058 | #endchar; 2059 | add_char("colon", 4, [ 2060 | shift(dot, (1,0)), 2061 | shift(dot, (2,7)), 2062 | ]) 2063 | 2064 | #beginchar(";", 4u#, 7u#, 0); 2065 | # pickup pencircle scaled (dotkoef*thin); 2066 | # drawdot (2,7); 2067 | # pickup pencircle scaled thin; 2068 | # draw (1,1)--(0,-2); 2069 | #endchar; 2070 | add_char("semicolon", 4, [ 2071 | shift(dot, (2,7)), 2072 | _draw2([((1,1),None),None,((0,-2),None)]), 2073 | ]) 2074 | 2075 | #beginchar(clqq, 4u#, 1u#, 0); 2076 | # draw (0,1)--(-1,-2); 2077 | # draw (2,1)--(1,-2); 2078 | #endchar; 2079 | add_char("quotedblbase", 4, [ 2080 | _draw2([((0,1),None),None,((-1,-2),None)]), 2081 | _draw2([((2,1),None),None,((1,-2),None)]), 2082 | ]) 2083 | 2084 | #beginchar(crqq, 4u#, 15u#, 0); 2085 | # draw (2,15)--(1.5,12); 2086 | # draw (4,15)--(3.5,12); 2087 | #endchar; 2088 | add_char("quotedblright", 4, [ 2089 | _draw2([((2,15),None),None,((1.5,12),None)]), 2090 | _draw2([((4,15),None),None,((3.5,12),None)]), 2091 | ]) 2092 | add_char("quotedblleft", 4, [ 2093 | _draw2([((2,15),None),None,((1.5,12),None)]), 2094 | _draw2([((4,15),None),None,((3.5,12),None)]), 2095 | ]) 2096 | add_char("quotedbl", 4, [ 2097 | _draw2([((2,15),None),None,((1.5,12),None)]), 2098 | _draw2([((4,15),None),None,((3.5,12),None)]), 2099 | ]) 2100 | 2101 | #beginchar(leftquota, 4u#, 15u#, 0); 2102 | # draw (0,15){down}..(1,12); 2103 | #endchar; 2104 | add_char("quoteleft", 4, [ 2105 | _draw2([((0,15),down),1,((1,12),(1,-1))]), 2106 | ]) 2107 | 2108 | #beginchar(rightquota, 4u#, 15u#, 0); 2109 | # draw (4,15){down}..(2,12); 2110 | #endchar; 2111 | add_char("quoteright", 4, [ 2112 | _draw2([((4,15),down),1,((2,12),(-1,-1))]), 2113 | ]) 2114 | add_char("quotesingle", 4, [ 2115 | _draw2([((4,15),down),1,((2,12),(-1,-1))]), 2116 | ]) 2117 | 2118 | 2119 | 2120 | ################################################################################ 2121 | 2122 | # Save 2123 | 2124 | unicode = { 2125 | "space": ["uni0020", "uni00A0"], 2126 | "asciitilde": ["uni007E", "uni223C"], 2127 | "hyphen": ["uni002D", "uni00AD", "uni2010", "uni2011"], 2128 | "quoteleft": ["uni2018"], 2129 | "quoteright": ["uni2019"], 2130 | } 2131 | 2132 | glyphs = [ 2133 | ".notdef", 2134 | "space", 2135 | 2136 | "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", 2137 | "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", 2138 | 2139 | "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", 2140 | "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", 2141 | 2142 | "Aacute", "Adieresis", "Ccaron", "Dcaron", "Eacute", "Ecaron", "Iacute", 2143 | "Lacute", "Lcaron", "Ncaron", "Oacute", "Ocircumflex", "Racute", "Rcaron", 2144 | "Scaron", "Tcaron", "Uacute", "Uring", "Yacute", "Zcaron", 2145 | 2146 | "aacute", "adieresis", "ccaron", "dcaron", "eacute", "ecaron", "iacute", 2147 | "lacute", "lcaron", "ncaron", "oacute", "ocircumflex", "racute", "rcaron", 2148 | "scaron", "tcaron", "uacute", "uring", "yacute", "zcaron", 2149 | 2150 | "ampersand", 2151 | 2152 | "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", 2153 | "nine", 2154 | 2155 | "period", "comma", "colon", "semicolon", "exclam", "question", 2156 | "quotesingle", "quotedbl", "quoteleft", "quoteright", "quotedblleft", 2157 | "quotedblright", "quotedblbase", "hyphen", 2158 | 2159 | "underscore", "parenleft", "parenright", "bracketleft", "bracketright", 2160 | "braceleft", "braceright", "slash", "bar", "backslash", "asterisk", "at", 2161 | "numbersign", 2162 | 2163 | "quotedbl.sc", 2164 | 2165 | "dollar", 2166 | 2167 | "percent", "perthousand", 2168 | 2169 | "plus", "minus", "multiply", "equal", "less", "greater", "asciicircum", 2170 | "asciitilde", 2171 | 2172 | 2173 | # Our specific glyphs, not in unicode: 2174 | 2175 | # Connecting curves 2176 | "begin", "begin_straight", "begin_x", "conn_s", "conn_sv", "conn_P", "end", 2177 | # Alternative versions 2178 | "sleft", "sdepth", "scaronleft", "scarondepth", "bnarrow", "onarrow", 2179 | "oacutenarrow", "ocircumflexnarrow", "vnarrow", "wnarrow", 2180 | # Helper token for OTF glyph substitution 2181 | "subs_token", 2182 | ] 2183 | 2184 | def fix_name(x): 2185 | """ 2186 | Take AGL name and create a filename that works on case insensitive 2187 | filesystems (macOS). 2188 | """ 2189 | if x[0] >= "A" and x[0] <= "Z": 2190 | x = x[0] + "_" + x[1:] 2191 | if x[0] == ".": 2192 | x = "_" + x[1:] 2193 | return x 2194 | 2195 | letters = [fix_name(x) for x in glyphs] 2196 | 2197 | current_dir = os.path.dirname(os.path.abspath(__file__)) 2198 | glyphs_dir = "../font.ufo/glyphs" 2199 | run(f"mkdir -p {glyphs_dir}") 2200 | s = "" 2201 | for letter in letters: 2202 | s += f"file-open:letter_{letter}.svg; select-by-id: path0; object-stroke-to-path; export-type:svg; export-do\n" 2203 | open("commands.txt", "w").write(s) 2204 | run("inkscape --shell < commands.txt") 2205 | for letter in letters: 2206 | run(f"python svg2glif.py letter_{letter}_out.svg") 2207 | run(f"cp letter_{letter}_out_out3.glif {glyphs_dir}/{letter}.glif") 2208 | 2209 | s = """\ 2210 | 2211 | 2212 | 2213 | \t 2214 | """ 2215 | for name in glyphs: 2216 | filename = fix_name(name) + ".glif" 2217 | s += f"\t\t{name}\n" 2218 | s += f"\t\t{filename}\n" 2219 | s += """\ 2220 | \t 2221 | 2222 | """ 2223 | open(f"{glyphs_dir}/contents.plist", "w").write(s) 2224 | 2225 | s = """\ 2226 | 2227 | 2228 | 2229 | \t 2230 | \t\tpublic.glyphOrder 2231 | \t\t 2232 | """ 2233 | for name in glyphs: 2234 | s += f"\t\t\t{name}\n" 2235 | s += """\ 2236 | \t\t 2237 | \t 2238 | 2239 | """ 2240 | open(f"{glyphs_dir}/../lib.plist", "w").write(s) 2241 | 2242 | s = "" 2243 | for name in glyphs: 2244 | s += f"{name}\t{name}" 2245 | if name in unicode: 2246 | s += "\t" + ",".join(unicode[name]) 2247 | s += "\n" 2248 | open(f"{glyphs_dir}/../../GlyphOrderAndAliasDB", "w").write(s) 2249 | --------------------------------------------------------------------------------