From 164005ab8a1f7a3c97415a0c64d87453c42fb6e8 Mon Sep 17 00:00:00 2001 From: Frederik Berlaen Date: Mon, 26 Oct 2020 13:37:33 +0100 Subject: [PATCH] initial and last commit --- _downloads/RAnchor_00.py | 9 + _downloads/RAnchor_01.py | 9 + _downloads/RComponent_00.py | 10 + _downloads/RComponent_01.py | 12 + _downloads/RContour_00.py | 9 + _downloads/RFont_00.py | 17 + _downloads/RFont_01.py | 8 + _downloads/RFont_02.py | 8 + _downloads/RFont_03.py | 17 + _downloads/RFont_04.py | 12 + _downloads/RFont_05.py | 12 + _downloads/RGlyph_00.py | 22 + _downloads/RGlyph_01.py | 28 + _downloads/RGlyph_02.py | 12 + _downloads/RGlyph_03.py | 21 + _downloads/RInfo_00.py | 21 + _downloads/RKerning_00.py | 11 + _downloads/RLib_00.py | 9 + _downloads/RPoint_00.py | 13 + _downloads/RSegment_00.py | 10 + _downloads/RSegment_01.py | 16 + _downloads/RSegment_02.py | 10 + _downloads/bPoint_00.py | 7 + _downloads/bPoint_01.py | 8 + _downloads/buildingAccents_00.py | 12 + _downloads/buildingAccents_01.py | 32 + _downloads/buildingAccents_02.py | 56 + _downloads/fontlabRemote_00.py | 2 + _downloads/fontlabRemote_01.py | 3 + _downloads/fontlabRemote_02.py | 7 + _downloads/fontlabRemote_03.py | 49 + _downloads/generatingFonts_00.py | 12 + _downloads/glifNames_00.py | 21 + _downloads/glyphMath_00.py | 28 + _downloads/interpol_00.py | 10 + _downloads/interpol_01.py | 14 + _downloads/interpol_02.py | 36 + _downloads/interpol_03.py | 5 + _downloads/interpol_04.py | 6 + _downloads/interpol_05.py | 16 + _downloads/interpol_06.py | 22 + _downloads/interpol_07.py | 37 + _downloads/interpol_08.py | 38 + _downloads/interpol_09.py | 25 + _downloads/interpolate_00.py | 4 + _downloads/interpolate_01.py | 4 + _downloads/interpolate_02.py | 18 + _downloads/kerning_00.py | 10 + _downloads/lowLevel_00.py | 6 + _downloads/makeUFO_00.py | 11 + _downloads/nonelab_00.py | 25 + _downloads/otFeatures_00.py | 12 + _downloads/otFeatures_01.py | 8 + _downloads/pen_00.py | 11 + _downloads/pens_00.py | 25 + _downloads/pens_01.py | 13 + _downloads/pens_02.py | 13 + _downloads/pens_03.py | 4 + _downloads/pens_04.py | 4 + _downloads/pens_05.py | 5 + _downloads/pens_06.py | 3 + _downloads/psHints_00.py | 11 + _downloads/psHints_01.py | 7 + _downloads/psHints_02.py | 18 + _downloads/psHints_03.py | 96 + _downloads/scripting_00.py | 4 + _downloads/scripting_01.py | 5 + _downloads/scripting_02.py | 4 + _downloads/session1_00.py | 2 + _downloads/session1_01.py | 3 + _downloads/session1_02.py | 3 + _downloads/session1_03.py | 7 + _downloads/session1_04.py | 16 + _downloads/session1_05.py | 22 + _downloads/session1_06.py | 14 + _downloads/session1_07.py | 11 + _downloads/session1_08.py | 11 + _downloads/session1_09.py | 18 + _downloads/session2_00.py | 16 + _downloads/session2_01.py | 21 + _downloads/session2_02.py | 18 + _downloads/session2_03.py | 9 + _downloads/session2_04.py | 10 + _downloads/session2_05.py | 12 + _downloads/session2_06.py | 9 + _downloads/session2_07.py | 37 + _downloads/session2_08.py | 15 + _downloads/session2_09.py | 45 + _downloads/session2_10.py | 10 + _downloads/session2_11.py | 15 + _downloads/session3_00.py | 12 + _downloads/session3_01.py | 23 + _downloads/session3_02.py | 12 + _downloads/session3_03.py | 11 + _downloads/session3_04.py | 22 + _downloads/session3_05.py | 28 + _downloads/session6_00.py | 10 + _downloads/session6_01.py | 25 + _downloads/session6_02.py | 13 + _downloads/session6_03.py | 24 + _downloads/session6_04.py | 40 + _downloads/session6_05.py | 14 + _downloads/session6_06.py | 7 + _downloads/session6_07.py | 46 + _downloads/session6_08.py | 40 + _downloads/session6_09.py | 9 + _downloads/session6_10.py | 3 + _downloads/session6_11.py | 11 + _downloads/session6_12.py | 15 + _downloads/transformations_00.py | 17 + _downloads/understandingContours_00.py | 4 + _downloads/understandingContours_02.py | 5 + _downloads/understandingContours_03.py | 7 + _images/ObjectModel.svg | 577 + _images/RAnchor.gif | Bin 0 -> 2073 bytes _images/RAnchor1.gif | Bin 0 -> 2073 bytes _images/RComponent.gif | Bin 0 -> 2185 bytes _images/RComponent1.gif | Bin 0 -> 2185 bytes _images/RContour.gif | Bin 0 -> 2088 bytes _images/RFont.gif | Bin 0 -> 2973 bytes _images/RFont1.gif | Bin 0 -> 2973 bytes _images/RGlyph.gif | Bin 0 -> 3186 bytes _images/RGlyph1.gif | Bin 0 -> 3186 bytes _images/RInfo.gif | Bin 0 -> 1929 bytes _images/RKerning.gif | Bin 0 -> 1955 bytes _images/RKerning1.gif | Bin 0 -> 1955 bytes _images/RPoint.gif | Bin 0 -> 1968 bytes _images/RSegment.gif | Bin 0 -> 2179 bytes _images/askstring_mac.jpg | Bin 0 -> 26295 bytes _images/askyesnocancel_mac.jpg | Bin 0 -> 26086 bytes _images/bPoint.gif | Bin 0 -> 1831 bytes _images/cent.gif | Bin 0 -> 42765 bytes _images/compatibility-scheme_2_01.gif | Bin 0 -> 1033 bytes _images/compatibility-scheme_2_02.gif | Bin 0 -> 1342 bytes _images/compatibility-scheme_2_03.gif | Bin 0 -> 2177 bytes _images/compatibility-scheme_2_04.gif | Bin 0 -> 1314 bytes _images/compatibility-scheme_2_05.gif | Bin 0 -> 1269 bytes _images/compatibility-scheme_2_06.gif | Bin 0 -> 1620 bytes _images/compatibility-scheme_2_07.gif | Bin 0 -> 1910 bytes _images/compatibility-scheme_2_08.gif | Bin 0 -> 2236 bytes _images/drawingexample.jpg | Bin 0 -> 24982 bytes _images/exportmenu.gif | Bin 0 -> 21453 bytes _images/findglyph_fl.jpg | Bin 0 -> 8863 bytes _images/flatten.gif | Bin 0 -> 5066 bytes _images/fontLib.gif | Bin 0 -> 1896 bytes _images/glyphinterpol.gif | Bin 0 -> 2579 bytes _images/glyphmath_examples_01.gif | Bin 0 -> 1707 bytes _images/glyphmath_examples_02.gif | Bin 0 -> 1105 bytes _images/glyphmath_examples_03.gif | Bin 0 -> 1480 bytes _images/glyphmath_examples_04.gif | Bin 0 -> 1097 bytes _images/glyphmath_examples_05.gif | Bin 0 -> 3183 bytes _images/halftone.gif | Bin 0 -> 4771 bytes _images/logo.gif | Bin 0 -> 3406 bytes _images/logo1.gif | Bin 0 -> 3406 bytes _images/message_mac.jpg | Bin 0 -> 23113 bytes _images/rasteriser.gif | Bin 0 -> 24922 bytes _images/selectfont_fl.jpg | Bin 0 -> 30630 bytes _images/selectglyph_fl.jpg | Bin 0 -> 36429 bytes _images/spike.gif | Bin 0 -> 7473 bytes _images/threshold.gif | Bin 0 -> 5111 bytes _images/ufo.jpg | Bin 0 -> 46669 bytes _sources/api/gString.rst.txt | 7 + _sources/api/glifLib.rst.txt | 6 + _sources/api/glifLib2.rst.txt | 6 + _sources/api/index.rst.txt | 19 + _sources/api/interface/all/all.rst.txt | 16 + _sources/api/interface/all/dialogs.rst.txt | 6 + .../api/interface/all/dialogs_default.rst.txt | 6 + .../all/dialogs_fontlab_legacy1.rst.txt | 6 + .../all/dialogs_fontlab_legacy2.rst.txt | 6 + .../api/interface/all/dialogs_legacy.rst.txt | 6 + .../interface/all/dialogs_mac_vanilla.rst.txt | 6 + _sources/api/interface/interface.rst.txt | 13 + _sources/api/interface/mac/mac.rst.txt | 6 + _sources/api/interface/win/win.rst.txt | 6 + _sources/api/misc/arrayTools.rst.txt | 6 + _sources/api/misc/bezierTools.rst.txt | 6 + _sources/api/misc/misc.rst.txt | 13 + _sources/api/misc/speedTestCase.rst.txt | 6 + _sources/api/misc/test.rst.txt | 6 + _sources/api/objects/index.rst.txt | 13 + _sources/api/objects/objectsBase.rst.txt | 6 + _sources/api/objects/objectsFF.rst.txt | 6 + _sources/api/objects/objectsFL.rst.txt | 6 + _sources/api/objects/objectsRF.rst.txt | 6 + _sources/api/pens/adapterPens.rst.txt | 6 + _sources/api/pens/angledMarginPen.rst.txt | 6 + _sources/api/pens/boundsPen.rst.txt | 6 + _sources/api/pens/digestPen.rst.txt | 6 + _sources/api/pens/filterPen.rst.txt | 6 + _sources/api/pens/flPen.rst.txt | 6 + _sources/api/pens/marginPen.rst.txt | 6 + _sources/api/pens/mathPens.rst.txt | 6 + _sources/api/pens/pens.rst.txt | 21 + _sources/api/pens/pointPen.rst.txt | 6 + _sources/api/pens/quartzPen.rst.txt | 6 + .../api/pens/reverseContourPointPen.rst.txt | 6 + _sources/api/pens/rfUFOPen.rst.txt | 6 + _sources/api/plistFromTree.rst.txt | 6 + _sources/api/plistlib.rst.txt | 6 + _sources/api/test/test.rst.txt | 21 + _sources/api/test/test_dialogs.rst.txt | 6 + _sources/api/test/test_glifLib.rst.txt | 6 + .../api/test/test_noneLabUFOReadWrite.rst.txt | 6 + _sources/api/test/test_objectsUFO.rst.txt | 6 + _sources/api/test/test_pens.rst.txt | 6 + _sources/api/test/test_psHints.rst.txt | 6 + _sources/api/tools/accentBuilder.rst.txt | 6 + .../api/tools/fontlabFeatureSplitter.rst.txt | 6 + _sources/api/tools/glifExport.rst.txt | 6 + _sources/api/tools/glifImport.rst.txt | 6 + _sources/api/tools/glyphConstruction.rst.txt | 6 + _sources/api/tools/glyphNameSchemes.rst.txt | 6 + _sources/api/tools/index.rst.txt | 24 + _sources/api/tools/objectDumper.rst.txt | 6 + _sources/api/tools/otFeatures.rst.txt | 6 + _sources/api/tools/proof.rst.txt | 6 + _sources/api/tools/remote.rst.txt | 6 + _sources/api/tools/rfPrefs.rst.txt | 6 + _sources/api/tools/toolsAll.rst.txt | 6 + _sources/api/tools/toolsFL.rst.txt | 6 + _sources/api/tools/toolsRF.rst.txt | 7 + _sources/api/ufoLib.rst.txt | 6 + _sources/api/world.rst.txt | 6 + _sources/api/xmlTreeBuilder.rst.txt | 6 + _sources/howtos/building_accents.rst.txt | 72 + _sources/howtos/fontlab_remote.rst.txt | 75 + _sources/howtos/generating_fonts.rst.txt | 54 + _sources/howtos/glifnames.rst.txt | 32 + _sources/howtos/glyphmath.rst.txt | 96 + _sources/howtos/index.rst.txt | 40 + _sources/howtos/interpolate.rst.txt | 73 + _sources/howtos/lowlevel.rst.txt | 16 + _sources/howtos/makeufo.rst.txt | 44 + _sources/howtos/ot_features.rst.txt | 47 + _sources/howtos/scripting.rst.txt | 108 + .../howtos/understanding_contours.rst.txt | 100 + _sources/howtos/use_lib.rst.txt | 39 + _sources/howtos/use_pens.rst.txt | 98 + _sources/howtos/use_transformations.rst.txt | 78 + _sources/howtos/world.rst.txt | 117 + _sources/index.rst.txt | 60 + _sources/intro/dialogs.rst.txt | 142 + _sources/intro/download.rst.txt | 35 + _sources/intro/gettingstarted.rst.txt | 23 + _sources/intro/glossary.rst.txt | 10 + _sources/intro/history.rst.txt | 148 + _sources/intro/index.rst.txt | 18 + _sources/intro/install.rst.txt | 96 + _sources/intro/intro.rst.txt | 54 + _sources/intro/limitations.rst.txt | 50 + _sources/intro/links.rst.txt | 26 + _sources/intro/summary.rst.txt | 12 + _sources/intro/tools.rst.txt | 54 + _sources/intro/ufo.rst.txt | 32 + _sources/objects/RAnchor.rst.txt | 87 + _sources/objects/RComponent.rst.txt | 92 + _sources/objects/RContour.rst.txt | 149 + _sources/objects/RFont.rst.txt | 224 + _sources/objects/RGlyph.rst.txt | 257 + _sources/objects/RInfo.rst.txt | 32 + _sources/objects/RKerning.rst.txt | 130 + _sources/objects/RPoint.rst.txt | 74 + _sources/objects/RSegment.rst.txt | 85 + _sources/objects/bPoint.rst.txt | 87 + _sources/objects/index.rst.txt | 22 + _sources/objects/libs.rst.txt | 38 + _sources/objects/model.rst.txt | 6 + _sources/objects/objects.rst.txt | 56 + _sources/objects/pens.rst.txt | 94 + _sources/objects/psHints.rst.txt | 162 + _sources/objects/psHintsGlyph.rst.txt | 61 + _sources/talks/dialogkit.rst.txt | 11 + _sources/talks/editors.rst.txt | 144 + _sources/talks/index.rst.txt | 41 + _sources/talks/interpolation.rst.txt | 209 + _sources/talks/python_basics.rst.txt | 102 + _sources/talks/session1.rst.txt | 178 + _sources/talks/session2.rst.txt | 199 + _sources/talks/session3.rst.txt | 110 + _sources/talks/session4.rst.txt | 103 + _sources/talks/session6.rst.txt | 138 + _static/_img/drawmodel.jpg | Bin 0 -> 6228 bytes _static/_img/drawmodel_header.jpg | Bin 0 -> 8410 bytes _static/_img/logo.gif | Bin 0 -> 3406 bytes _static/_img/offdrawmodel_02.gif | Bin 0 -> 1945 bytes _static/_img/offdrawmodel_05.gif | Bin 0 -> 1975 bytes _static/_img/offdrawmodel_07.gif | Bin 0 -> 3126 bytes _static/_img/offdrawmodel_11.gif | Bin 0 -> 2020 bytes _static/_img/offdrawmodel_13.gif | Bin 0 -> 1926 bytes _static/_img/offdrawmodel_17.gif | Bin 0 -> 3325 bytes _static/_img/offdrawmodel_20.gif | Bin 0 -> 2125 bytes _static/_img/offdrawmodel_22.gif | Bin 0 -> 2018 bytes _static/_img/offdrawmodel_26.gif | Bin 0 -> 2251 bytes _static/_img/offdrawmodel_28.gif | Bin 0 -> 1893 bytes _static/_img/offdrawmodel_30.gif | Bin 0 -> 2132 bytes _static/_img/offdrawmodel_34.gif | Bin 0 -> 2239 bytes _static/_img/ondrawmodel_02.gif | Bin 0 -> 1896 bytes _static/_img/ondrawmodel_05.gif | Bin 0 -> 1929 bytes _static/_img/ondrawmodel_07.gif | Bin 0 -> 2973 bytes _static/_img/ondrawmodel_11.gif | Bin 0 -> 1955 bytes _static/_img/ondrawmodel_13.gif | Bin 0 -> 1870 bytes _static/_img/ondrawmodel_17.gif | Bin 0 -> 3186 bytes _static/_img/ondrawmodel_20.gif | Bin 0 -> 2073 bytes _static/_img/ondrawmodel_22.gif | Bin 0 -> 1968 bytes _static/_img/ondrawmodel_26.gif | Bin 0 -> 2185 bytes _static/_img/ondrawmodel_28.gif | Bin 0 -> 1831 bytes _static/_img/ondrawmodel_30.gif | Bin 0 -> 2088 bytes _static/_img/ondrawmodel_34.gif | Bin 0 -> 2179 bytes _static/ajax-loader.gif | Bin 0 -> 673 bytes _static/basic.css | 632 + _static/comment-bright.png | Bin 0 -> 756 bytes _static/comment-close.png | Bin 0 -> 829 bytes _static/comment.png | Bin 0 -> 641 bytes _static/doctools.js | 287 + _static/down-pressed.png | Bin 0 -> 222 bytes _static/down.png | Bin 0 -> 202 bytes _static/file.png | Bin 0 -> 286 bytes _static/jquery-3.1.0.js | 10074 ++++++++++++++++ _static/jquery.js | 4 + _static/minus.png | Bin 0 -> 90 bytes _static/plus.png | Bin 0 -> 90 bytes _static/pygments.css | 69 + _static/robofab.css | 194 + _static/robofab.sass | 230 + _static/sass2css.py | 22 + _static/searchtools.js | 758 ++ _static/underscore-1.3.1.js | 999 ++ _static/underscore.js | 31 + _static/up-pressed.png | Bin 0 -> 214 bytes _static/up.png | Bin 0 -> 203 bytes _static/websupport.js | 808 ++ api/gString.html | 210 + api/glifLib.html | 332 + api/glifLib2.html | 347 + api/index.html | 158 + api/interface/all/all.html | 143 + api/interface/all/dialogs.html | 128 + api/interface/all/dialogs_default.html | 132 + .../all/dialogs_fontlab_legacy1.html | 128 + .../all/dialogs_fontlab_legacy2.html | 169 + api/interface/all/dialogs_legacy.html | 128 + api/interface/all/dialogs_mac_vanilla.html | 128 + api/interface/interface.html | 140 + api/interface/mac/mac.html | 130 + api/interface/win/win.html | 130 + api/misc/arrayTools.html | 221 + api/misc/bezierTools.html | 287 + api/misc/misc.html | 136 + api/misc/speedTestCase.html | 130 + api/misc/test.html | 139 + api/objects/index.html | 150 + api/objects/objectsBase.html | 1119 ++ api/objects/objectsFF.html | 142 + api/objects/objectsFL.html | 142 + api/objects/objectsRF.html | 205 + api/pens/adapterPens.html | 178 + api/pens/angledMarginPen.html | 142 + api/pens/boundsPen.html | 172 + api/pens/digestPen.html | 171 + api/pens/filterPen.html | 222 + api/pens/flPen.html | 142 + api/pens/marginPen.html | 176 + api/pens/mathPens.html | 157 + api/pens/pens.html | 158 + api/pens/pointPen.html | 152 + api/pens/quartzPen.html | 148 + api/pens/reverseContourPointPen.html | 153 + api/pens/rfUFOPen.html | 142 + api/plistFromTree.html | 151 + api/plistlib.html | 253 + api/test/test.html | 138 + api/test/test_dialogs.html | 128 + api/test/test_glifLib.html | 128 + api/test/test_noneLabUFOReadWrite.html | 128 + api/test/test_objectsUFO.html | 129 + api/test/test_pens.html | 130 + api/test/test_psHints.html | 235 + api/tools/accentBuilder.html | 142 + api/tools/fontlabFeatureSplitter.html | 152 + api/tools/glifExport.html | 332 + api/tools/glifImport.html | 142 + api/tools/glyphConstruction.html | 142 + api/tools/glyphNameSchemes.html | 157 + api/tools/index.html | 163 + api/tools/objectDumper.html | 150 + api/tools/otFeatures.html | 142 + api/tools/proof.html | 201 + api/tools/remote.html | 142 + api/tools/rfPrefs.html | 172 + api/tools/toolsAll.html | 149 + api/tools/toolsFL.html | 277 + api/tools/toolsRF.html | 143 + api/ufoLib.html | 357 + api/world.html | 142 + api/xmlTreeBuilder.html | 142 + genindex.html | 1553 +++ howtos/building_accents.html | 299 + howtos/fontlab_remote.html | 265 + howtos/generating_fonts.html | 220 + howtos/glifnames.html | 189 + howtos/glyphmath.html | 250 + howtos/index.html | 162 + howtos/interpolate.html | 226 + howtos/lowlevel.html | 159 + howtos/makeufo.html | 198 + howtos/ot_features.html | 209 + howtos/scripting.html | 246 + howtos/understanding_contours.html | 239 + howtos/use_lib.html | 175 + howtos/use_pens.html | 287 + howtos/use_transformations.html | 247 + howtos/world.html | 238 + index.html | 175 + intro/dialogs.html | 276 + intro/download.html | 169 + intro/gettingstarted.html | 161 + intro/glossary.html | 148 + intro/history.html | 266 + intro/index.html | 158 + intro/install.html | 229 + intro/intro.html | 182 + intro/limitations.html | 183 + intro/links.html | 169 + intro/summary.html | 147 + intro/tools.html | 206 + intro/ufo.html | 162 + objects.inv | Bin 0 -> 5871 bytes objects/RAnchor.html | 265 + objects/RComponent.html | 275 + objects/RContour.html | 341 + objects/RFont.html | 495 + objects/RGlyph.html | 581 + objects/RInfo.html | 186 + objects/RKerning.html | 329 + objects/RPoint.html | 245 + objects/RSegment.html | 279 + objects/bPoint.html | 256 + objects/index.html | 162 + objects/libs.html | 185 + objects/model.html | 143 + objects/objects.html | 194 + objects/pens.html | 265 + objects/psHints.html | 474 + objects/psHintsGlyph.html | 212 + old/credits.html | 56 + old/default.css | 465 + old/history.html | 350 + old/howto/architecture.jpg | Bin 0 -> 45342 bytes old/howto/buildingaccents.html | 83 + old/howto/drawingexample.jpg | Bin 0 -> 24982 bytes old/howto/examples/buildaccentsBuilder.py | 32 + old/howto/examples/buildaccentsCustom.py | 59 + old/howto/examples/gmathFun.py | 29 + old/howto/examples/interpolGlyphs.py | 11 + old/howto/examples/interpolStraight.py | 19 + old/howto/examples/makeufoBinary.py | 12 + old/howto/examples/usageBuildaccents.py | 13 + old/howto/examples/usageFlremote.py | 53 + old/howto/examples/usageGeneratefonts.py | 13 + old/howto/examples/usageGlifnames.py | 22 + old/howto/examples/usagePens.py | 23 + old/howto/examples/usageTransform.py | 18 + old/howto/examples/usageWorld.py | 11 + old/howto/examples/useDigestPointPen.py | 14 + old/howto/examples/useDigestPtStructure.py | 13 + old/howto/features.html | 71 + old/howto/fontlabremote.html | 92 + old/howto/generatefonts.html | 108 + old/howto/glifnames.html | 54 + old/howto/glyphmath.html | 90 + old/howto/hints.html | 68 + old/howto/index.html | 74 + old/howto/interpolate.html | 90 + old/howto/lowlevel.html | 51 + old/howto/makeufo.html | 102 + old/howto/objectinheritance.jpg | Bin 0 -> 28234 bytes old/howto/scripting.html | 101 + old/howto/understandcontours.html | 78 + old/howto/usepens.html | 94 + old/howto/usethelib.html | 51 + old/howto/usetransformations.html | 72 + old/howto/world.html | 95 + old/img/drawmodel.jpg | Bin 0 -> 6228 bytes old/img/drawmodel_header.jpg | Bin 0 -> 8410 bytes old/img/flatten.gif | Bin 0 -> 5066 bytes old/img/halftone.gif | Bin 0 -> 4771 bytes old/img/logo.gif | Bin 0 -> 3406 bytes old/img/offdrawmodel_02.gif | Bin 0 -> 1945 bytes old/img/offdrawmodel_05.gif | Bin 0 -> 1975 bytes old/img/offdrawmodel_07.gif | Bin 0 -> 3126 bytes old/img/offdrawmodel_11.gif | Bin 0 -> 2020 bytes old/img/offdrawmodel_13.gif | Bin 0 -> 1926 bytes old/img/offdrawmodel_17.gif | Bin 0 -> 3325 bytes old/img/offdrawmodel_20.gif | Bin 0 -> 2125 bytes old/img/offdrawmodel_22.gif | Bin 0 -> 2018 bytes old/img/offdrawmodel_26.gif | Bin 0 -> 2251 bytes old/img/offdrawmodel_28.gif | Bin 0 -> 1893 bytes old/img/offdrawmodel_30.gif | Bin 0 -> 2132 bytes old/img/offdrawmodel_34.gif | Bin 0 -> 2239 bytes old/img/ondrawmodel_02.gif | Bin 0 -> 1896 bytes old/img/ondrawmodel_05.gif | Bin 0 -> 1929 bytes old/img/ondrawmodel_07.gif | Bin 0 -> 2973 bytes old/img/ondrawmodel_11.gif | Bin 0 -> 1955 bytes old/img/ondrawmodel_13.gif | Bin 0 -> 1870 bytes old/img/ondrawmodel_17.gif | Bin 0 -> 3186 bytes old/img/ondrawmodel_20.gif | Bin 0 -> 2073 bytes old/img/ondrawmodel_22.gif | Bin 0 -> 1968 bytes old/img/ondrawmodel_26.gif | Bin 0 -> 2185 bytes old/img/ondrawmodel_28.gif | Bin 0 -> 1831 bytes old/img/ondrawmodel_30.gif | Bin 0 -> 2088 bytes old/img/ondrawmodel_34.gif | Bin 0 -> 2179 bytes old/img/spike.gif | Bin 0 -> 7473 bytes old/img/temptitle.gif | Bin 0 -> 2009 bytes old/img/threshold.gif | Bin 0 -> 5111 bytes old/index.html | 62 + old/install.html | 202 + old/intro.html | 88 + old/limitations.html | 97 + old/objects/anchor.html | 67 + old/objects/bpoint.html | 70 + old/objects/component.html | 82 + old/objects/contour.html | 115 + old/objects/contours.jpg | Bin 0 -> 25257 bytes old/objects/contours_bpoints.jpg | Bin 0 -> 25079 bytes old/objects/contours_points.jpg | Bin 0 -> 25022 bytes old/objects/contours_segments.jpg | Bin 0 -> 25679 bytes old/objects/contours_segments_points.jpg | Bin 0 -> 28134 bytes old/objects/examples/anchorAttributes.py | 8 + old/objects/examples/anchorMethods.py | 6 + old/objects/examples/bpointAttributes.py | 7 + old/objects/examples/bpointMethods.py | 6 + old/objects/examples/componentAttributes.py | 12 + old/objects/examples/componentMethods.py | 6 + old/objects/examples/contourMethods.py | 6 + old/objects/examples/fontAttributes.py | 17 + old/objects/examples/fontIterate.py | 9 + old/objects/examples/fontMethods.py | 11 + old/objects/examples/fontMethodsFL.py | 11 + old/objects/examples/glyphAttributes.py | 29 + old/objects/examples/glyphMethods.py | 12 + old/objects/examples/remapComponent.py | 21 + old/objects/examples/segmentAttributes.py | 16 + old/objects/examples/segmentMethods.py | 10 + old/objects/examples/usageAnchor.py | 8 + old/objects/examples/usageBpoint.py | 7 + old/objects/examples/usageComponent.py | 7 + old/objects/examples/usageContour.py | 8 + old/objects/examples/usageFont.py | 16 + old/objects/examples/usageGlyph.py | 23 + old/objects/examples/usageInfo.py | 21 + old/objects/examples/usageKerning.py | 12 + old/objects/examples/usageLib.py | 10 + old/objects/examples/usagePSHintData.py | 99 + old/objects/examples/usagePen.py | 10 + old/objects/examples/usagePoint.py | 13 + old/objects/examples/usageSegment.py | 11 + old/objects/font.html | 181 + old/objects/generic.html | 26 + old/objects/glyph.html | 321 + old/objects/index.html | 79 + old/objects/info.html | 50 + old/objects/kerning.html | 86 + old/objects/lib.html | 52 + old/objects/model.html | 105 + old/objects/objectModel.jpg | Bin 0 -> 76925 bytes old/objects/pen.html | 80 + old/objects/point.html | 82 + old/objects/pshints.html | 94 + old/objects/pshintsGlyph.html | 60 + old/objects/segment.html | 81 + old/print.css | 208 + old/py2html.css | 120 + old/robothon/.afpDeleted32421152 | 34 + old/robothon/.afpDeleted33791704 | 929 ++ .../CONV_CS5_AdobeTypekit-h-lightBG.svg | 71 + old/robothon/H_and_co.svg | 132 + old/robothon/commercial-r.svg | 63 + old/robothon/fonts-by-hco-rgb-300x100.pdf | Bin 0 -> 17541 bytes old/robothon/foosball/test.py | 11 + old/robothon/index.html | 47 + old/robothon/index_old.html | 34 + old/robothon/index_sold_out_2015.html | 929 ++ old/robothon/kabk_logo_rood.png | Bin 0 -> 37684 bytes old/robothon/references.html | 192 + old/robothon/robothon.css | 567 + old/robothon/robothon09icon.jpg | Bin 0 -> 146446 bytes old/robothon/robothon2015_logo.jpg | Bin 0 -> 43546 bytes old/robothon/robothon2015_logo_2.jpg | Bin 0 -> 69147 bytes old/robothon/th-27_kabk_logo_rood.png | Bin 0 -> 17966 bytes old/robothon/twitter-bird-16x16.png | Bin 0 -> 1509 bytes old/robothon2012/fonts.css | 51 + old/robothon2012/img/logo_white.png | Bin 0 -> 52086 bytes old/robothon2012/img/logo_white_blackhole.png | Bin 0 -> 65499 bytes .../img/logo_white_blackhole_fix.png | Bin 0 -> 44209 bytes .../img/logo_white_blackhole_space.png | Bin 0 -> 53877 bytes old/robothon2012/index.html | 415 + old/robothon2012/index_webcast.html | 449 + old/robothon2012/screen.css | 326 + old/styles.css | 117 + old/talks/basic.html | 78 + old/talks/cent.gif | Bin 0 -> 42765 bytes old/talks/compatibility-scheme_2_01.gif | Bin 0 -> 1033 bytes old/talks/compatibility-scheme_2_02.gif | Bin 0 -> 1342 bytes old/talks/compatibility-scheme_2_03.gif | Bin 0 -> 2177 bytes old/talks/compatibility-scheme_2_04.gif | Bin 0 -> 1314 bytes old/talks/compatibility-scheme_2_05.gif | Bin 0 -> 1269 bytes old/talks/compatibility-scheme_2_06.gif | Bin 0 -> 1620 bytes old/talks/compatibility-scheme_2_07.gif | Bin 0 -> 1910 bytes old/talks/compatibility-scheme_2_08.gif | Bin 0 -> 2236 bytes old/talks/condensor.jpg | Bin 0 -> 6275 bytes old/talks/dialogkit.html | 41 + old/talks/examples/aGlyphParent.py | 10 + old/talks/examples/allFontsFontInfo.py | 10 + old/talks/examples/batchGenerate.py | 7 + old/talks/examples/batchInterpolate.py | 26 + old/talks/examples/batchSaveAs.py | 14 + old/talks/examples/buildingAccents1.py | 21 + old/talks/examples/compileGlyph.py | 28 + old/talks/examples/cookieCutter.py | 18 + old/talks/examples/drawStuffWithPen.py | 37 + old/talks/examples/editNameTable.py | Bin 0 -> 689 bytes old/talks/examples/fileWalker.py | Bin 0 -> 1178 bytes old/talks/examples/floatingPointGlyph.py | Bin 0 -> 820 bytes old/talks/examples/fontLabRemote.py | 25 + old/talks/examples/getSomeGlyphs.py | 10 + old/talks/examples/glyphCondensor.py | Bin 0 -> 710 bytes old/talks/examples/glyphMathOperations.py | 36 + old/talks/examples/index.html | 168 + old/talks/examples/infoAutonaming.py | 14 + old/talks/examples/interpolateFontSeries.py | 42 + old/talks/examples/interpolateGlyphs.py | 7 + old/talks/examples/interpolateSeries.py | 10 + old/talks/examples/interpolateTwoFonts.py | 18 + old/talks/examples/iterateContour.py | 13 + old/talks/examples/iterateFont.py | 10 + old/talks/examples/iterateGlyph.py | 12 + old/talks/examples/iteratePoints.py | 9 + old/talks/examples/makeFontInfoReport.py | Bin 0 -> 606 bytes old/talks/examples/mergeTwoFonts.py | 41 + old/talks/examples/prepareInterpolGlyph.py | 14 + old/talks/examples/printingPen.py | 15 + old/talks/examples/remoteEventDemo.py | 15 + old/talks/examples/robustBatchGenerate.py | 53 + old/talks/examples/setGuideLinesOnAverage.py | 63 + old/talks/examples/showEncoding.py | Bin 0 -> 294 bytes old/talks/examples/showNamingRecords.py | Bin 0 -> 201 bytes old/talks/examples/sillyRasteriser.py | 47 + old/talks/examples/someFontInfoAttributes.py | 14 + old/talks/examples/someFontInfoAttributes2.py | 20 + old/talks/examples/someGlyphAttributes.py | 16 + old/talks/examples/someGlyphAttributes2.py | 19 + old/talks/examples/someNameTableAttrs.py | 30 + old/talks/examples/test.py | 22 + old/talks/examples/transformGlyph.py | 20 + old/talks/examples/usingCoreGraphicsOSX.py | 26 + old/talks/examples/variousHintFunctions.py | 224 + old/talks/examples/workWithKerning1.py | 16 + old/talks/examples/workWithKerning2.py | 22 + old/talks/examples/workWithKerning3.py | 10 + old/talks/examples/workWithKerning4.py | 9 + old/talks/exportmenu.gif | Bin 0 -> 21453 bytes old/talks/glyphMath.gif | Bin 0 -> 7596 bytes old/talks/glyphinterpol.gif | Bin 0 -> 2579 bytes old/talks/glyphmath_examples_01.gif | Bin 0 -> 1707 bytes old/talks/glyphmath_examples_02.gif | Bin 0 -> 1105 bytes old/talks/glyphmath_examples_03.gif | Bin 0 -> 1480 bytes old/talks/glyphmath_examples_04.gif | Bin 0 -> 1097 bytes old/talks/glyphmath_examples_05.gif | Bin 0 -> 3183 bytes old/talks/index.html | 72 + old/talks/introduction.html | 48 + old/talks/printBooklet.html | 1937 +++ old/talks/printConferenceBooklet.html | 2354 ++++ old/talks/printNoneLab.html | 397 + old/talks/rasteriser.gif | Bin 0 -> 24922 bytes old/talks/robofab_session1.html | 151 + old/talks/robofab_session2.html | 181 + old/talks/robofab_session3.html | 124 + old/talks/robofab_session4.html | 220 + old/talks/robofab_session5.html | 386 + old/talks/robofab_session6.html | Bin 0 -> 40596 bytes old/talks/robothon06_logo.gif | Bin 0 -> 11937 bytes old/talks/ufo.jpg | Bin 0 -> 46669 bytes old/talks09/UFO_print.jpg | Bin 0 -> 63502 bytes old/talks09/basic.html | 96 + old/talks09/cent.gif | Bin 0 -> 42765 bytes old/talks09/compatibility-scheme_2_01.gif | Bin 0 -> 1033 bytes old/talks09/compatibility-scheme_2_02.gif | Bin 0 -> 1342 bytes old/talks09/compatibility-scheme_2_03.gif | Bin 0 -> 2177 bytes old/talks09/compatibility-scheme_2_04.gif | Bin 0 -> 1314 bytes old/talks09/compatibility-scheme_2_05.gif | Bin 0 -> 1269 bytes old/talks09/compatibility-scheme_2_06.gif | Bin 0 -> 1620 bytes old/talks09/compatibility-scheme_2_07.gif | Bin 0 -> 1910 bytes old/talks09/compatibility-scheme_2_08.gif | Bin 0 -> 2236 bytes old/talks09/condensor.jpg | Bin 0 -> 6275 bytes old/talks09/dialogkit.html | 38 + old/talks09/examples/aGlyphParent.py | 10 + old/talks09/examples/allFontsFontInfo.py | 10 + old/talks09/examples/batchGenerate.py | 7 + old/talks09/examples/batchInterpolate.py | 26 + old/talks09/examples/batchSaveAs.py | 14 + old/talks09/examples/buildingAccents1.py | 21 + old/talks09/examples/compileGlyph.py | 28 + old/talks09/examples/cookieCutter.py | 18 + old/talks09/examples/drawStuffWithPen.py | 37 + old/talks09/examples/editNameTable.py | Bin 0 -> 692 bytes old/talks09/examples/fileWalker.py | Bin 0 -> 1181 bytes old/talks09/examples/floatingPointGlyph.py | Bin 0 -> 823 bytes old/talks09/examples/fontLabRemote.py | 25 + old/talks09/examples/getSomeGlyphs.py | 10 + old/talks09/examples/glyphCondensor.py | Bin 0 -> 713 bytes old/talks09/examples/glyphMathOperations.py | 36 + old/talks09/examples/infoAutonaming.py | 14 + old/talks09/examples/interpolateFontSeries.py | 41 + old/talks09/examples/interpolateGlyphs.py | 7 + old/talks09/examples/interpolateSeries.py | 10 + old/talks09/examples/interpolateTwoFonts.py | 18 + old/talks09/examples/iterateContour.py | 13 + old/talks09/examples/iterateFont.py | 10 + old/talks09/examples/iterateGlyph.py | 12 + old/talks09/examples/iteratePoints.py | 9 + old/talks09/examples/makeFontInfoReport.py | Bin 0 -> 606 bytes old/talks09/examples/mergeTwoFonts.py | 41 + old/talks09/examples/prepareInterpolGlyph.py | 14 + old/talks09/examples/printingPen.py | 15 + old/talks09/examples/remoteEventDemo.py | 15 + old/talks09/examples/robustBatchGenerate.py | 53 + .../examples/setGuideLinesOnAverage.py | 63 + old/talks09/examples/showEncoding.py | Bin 0 -> 297 bytes old/talks09/examples/showNamingRecords.py | Bin 0 -> 204 bytes old/talks09/examples/sillyRasteriser.py | 47 + .../examples/someFontInfoAttributes.py | 14 + .../examples/someFontInfoAttributes2.py | 20 + old/talks09/examples/someGlyphAttributes.py | 16 + old/talks09/examples/someGlyphAttributes2.py | 15 + old/talks09/examples/someNameTableAttrs.py | 30 + old/talks09/examples/test.py | 24 + old/talks09/examples/transformGlyph.py | 20 + old/talks09/examples/usingCoreGraphicsOSX.py | 28 + old/talks09/examples/variousHintFunctions.py | 225 + old/talks09/examples/workWithKerning1.py | 16 + old/talks09/examples/workWithKerning2.py | 22 + old/talks09/examples/workWithKerning3.py | 10 + old/talks09/examples/workWithKerning4.py | 9 + old/talks09/exportmenu.gif | Bin 0 -> 21453 bytes old/talks09/fabPythonBasics.html | 99 + old/talks09/glyphMath.gif | Bin 0 -> 7596 bytes old/talks09/glyphinterpol.gif | Bin 0 -> 2579 bytes old/talks09/glyphmath_examples_01.gif | Bin 0 -> 1707 bytes old/talks09/glyphmath_examples_02.gif | Bin 0 -> 1105 bytes old/talks09/glyphmath_examples_03.gif | Bin 0 -> 1480 bytes old/talks09/glyphmath_examples_04.gif | Bin 0 -> 1097 bytes old/talks09/glyphmath_examples_05.gif | Bin 0 -> 3183 bytes old/talks09/index.html | 53 + old/talks09/printBooklet.html | 2079 ++++ old/talks09/rasteriser.gif | Bin 0 -> 24922 bytes old/talks09/robofab_session1.html | 178 + old/talks09/robofab_session2.html | 210 + old/talks09/robofab_session3.html | 148 + old/talks09/robofab_session4.html | 244 + old/talks09/robofab_session5.html | 368 + old/talks09/robofab_session6.html | Bin 0 -> 41469 bytes old/talks09/robothon06_logo.gif | Bin 0 -> 11937 bytes old/talks09/ufo.jpg | Bin 0 -> 46669 bytes old/tools/askstring_mac.jpg | Bin 0 -> 26295 bytes old/tools/askyesnocancel_mac.jpg | Bin 0 -> 26086 bytes old/tools/dialogs.html | 131 + old/tools/findglyph_fl.jpg | Bin 0 -> 8863 bytes old/tools/index.html | 52 + old/tools/message_mac.jpg | Bin 0 -> 23113 bytes old/tools/selectfont_fl.jpg | Bin 0 -> 30630 bytes old/tools/selectglyph_fl.jpg | Bin 0 -> 36429 bytes old/tools/tool.html | 88 + old/ufo/glif.html | 343 + old/ufo/index.html | 70 + old/ufo/pen.html | 114 + old/ufo/plist.html | 72 + old/ufo/specification.html | 349 + old/ufo/xmltext.jpg | Bin 0 -> 68828 bytes py-modindex.html | 386 + search.html | 148 + searchindex.js | 1 + talks/dialogkit.html | 145 + talks/editors.html | 260 + talks/index.html | 164 + talks/interpolation.html | 584 + talks/python_basics.html | 239 + talks/session1.html | 398 + talks/session2.html | 520 + talks/session3.html | 340 + talks/session4.html | 292 + talks/session6.html | 504 + 792 files changed, 73032 insertions(+) create mode 100644 _downloads/RAnchor_00.py create mode 100644 _downloads/RAnchor_01.py create mode 100644 _downloads/RComponent_00.py create mode 100644 _downloads/RComponent_01.py create mode 100644 _downloads/RContour_00.py create mode 100644 _downloads/RFont_00.py create mode 100644 _downloads/RFont_01.py create mode 100644 _downloads/RFont_02.py create mode 100644 _downloads/RFont_03.py create mode 100644 _downloads/RFont_04.py create mode 100644 _downloads/RFont_05.py create mode 100644 _downloads/RGlyph_00.py create mode 100644 _downloads/RGlyph_01.py create mode 100644 _downloads/RGlyph_02.py create mode 100644 _downloads/RGlyph_03.py create mode 100644 _downloads/RInfo_00.py create mode 100644 _downloads/RKerning_00.py create mode 100644 _downloads/RLib_00.py create mode 100644 _downloads/RPoint_00.py create mode 100644 _downloads/RSegment_00.py create mode 100644 _downloads/RSegment_01.py create mode 100644 _downloads/RSegment_02.py create mode 100644 _downloads/bPoint_00.py create mode 100644 _downloads/bPoint_01.py create mode 100644 _downloads/buildingAccents_00.py create mode 100644 _downloads/buildingAccents_01.py create mode 100644 _downloads/buildingAccents_02.py create mode 100644 _downloads/fontlabRemote_00.py create mode 100644 _downloads/fontlabRemote_01.py create mode 100644 _downloads/fontlabRemote_02.py create mode 100644 _downloads/fontlabRemote_03.py create mode 100644 _downloads/generatingFonts_00.py create mode 100644 _downloads/glifNames_00.py create mode 100644 _downloads/glyphMath_00.py create mode 100644 _downloads/interpol_00.py create mode 100644 _downloads/interpol_01.py create mode 100644 _downloads/interpol_02.py create mode 100644 _downloads/interpol_03.py create mode 100644 _downloads/interpol_04.py create mode 100644 _downloads/interpol_05.py create mode 100644 _downloads/interpol_06.py create mode 100644 _downloads/interpol_07.py create mode 100644 _downloads/interpol_08.py create mode 100644 _downloads/interpol_09.py create mode 100644 _downloads/interpolate_00.py create mode 100644 _downloads/interpolate_01.py create mode 100644 _downloads/interpolate_02.py create mode 100644 _downloads/kerning_00.py create mode 100644 _downloads/lowLevel_00.py create mode 100644 _downloads/makeUFO_00.py create mode 100644 _downloads/nonelab_00.py create mode 100644 _downloads/otFeatures_00.py create mode 100644 _downloads/otFeatures_01.py create mode 100644 _downloads/pen_00.py create mode 100644 _downloads/pens_00.py create mode 100644 _downloads/pens_01.py create mode 100644 _downloads/pens_02.py create mode 100644 _downloads/pens_03.py create mode 100644 _downloads/pens_04.py create mode 100644 _downloads/pens_05.py create mode 100644 _downloads/pens_06.py create mode 100644 _downloads/psHints_00.py create mode 100644 _downloads/psHints_01.py create mode 100644 _downloads/psHints_02.py create mode 100644 _downloads/psHints_03.py create mode 100644 _downloads/scripting_00.py create mode 100644 _downloads/scripting_01.py create mode 100644 _downloads/scripting_02.py create mode 100644 _downloads/session1_00.py create mode 100644 _downloads/session1_01.py create mode 100644 _downloads/session1_02.py create mode 100644 _downloads/session1_03.py create mode 100644 _downloads/session1_04.py create mode 100644 _downloads/session1_05.py create mode 100644 _downloads/session1_06.py create mode 100644 _downloads/session1_07.py create mode 100644 _downloads/session1_08.py create mode 100644 _downloads/session1_09.py create mode 100644 _downloads/session2_00.py create mode 100644 _downloads/session2_01.py create mode 100644 _downloads/session2_02.py create mode 100644 _downloads/session2_03.py create mode 100644 _downloads/session2_04.py create mode 100644 _downloads/session2_05.py create mode 100644 _downloads/session2_06.py create mode 100644 _downloads/session2_07.py create mode 100644 _downloads/session2_08.py create mode 100644 _downloads/session2_09.py create mode 100644 _downloads/session2_10.py create mode 100644 _downloads/session2_11.py create mode 100644 _downloads/session3_00.py create mode 100644 _downloads/session3_01.py create mode 100644 _downloads/session3_02.py create mode 100644 _downloads/session3_03.py create mode 100644 _downloads/session3_04.py create mode 100644 _downloads/session3_05.py create mode 100644 _downloads/session6_00.py create mode 100644 _downloads/session6_01.py create mode 100644 _downloads/session6_02.py create mode 100644 _downloads/session6_03.py create mode 100644 _downloads/session6_04.py create mode 100644 _downloads/session6_05.py create mode 100644 _downloads/session6_06.py create mode 100644 _downloads/session6_07.py create mode 100644 _downloads/session6_08.py create mode 100644 _downloads/session6_09.py create mode 100644 _downloads/session6_10.py create mode 100644 _downloads/session6_11.py create mode 100644 _downloads/session6_12.py create mode 100644 _downloads/transformations_00.py create mode 100644 _downloads/understandingContours_00.py create mode 100644 _downloads/understandingContours_02.py create mode 100644 _downloads/understandingContours_03.py create mode 100644 _images/ObjectModel.svg create mode 100644 _images/RAnchor.gif create mode 100644 _images/RAnchor1.gif create mode 100644 _images/RComponent.gif create mode 100644 _images/RComponent1.gif create mode 100644 _images/RContour.gif create mode 100644 _images/RFont.gif create mode 100644 _images/RFont1.gif create mode 100644 _images/RGlyph.gif create mode 100644 _images/RGlyph1.gif create mode 100644 _images/RInfo.gif create mode 100644 _images/RKerning.gif create mode 100644 _images/RKerning1.gif create mode 100644 _images/RPoint.gif create mode 100644 _images/RSegment.gif create mode 100644 _images/askstring_mac.jpg create mode 100644 _images/askyesnocancel_mac.jpg create mode 100644 _images/bPoint.gif create mode 100644 _images/cent.gif create mode 100644 _images/compatibility-scheme_2_01.gif create mode 100644 _images/compatibility-scheme_2_02.gif create mode 100644 _images/compatibility-scheme_2_03.gif create mode 100644 _images/compatibility-scheme_2_04.gif create mode 100644 _images/compatibility-scheme_2_05.gif create mode 100644 _images/compatibility-scheme_2_06.gif create mode 100644 _images/compatibility-scheme_2_07.gif create mode 100644 _images/compatibility-scheme_2_08.gif create mode 100644 _images/drawingexample.jpg create mode 100644 _images/exportmenu.gif create mode 100644 _images/findglyph_fl.jpg create mode 100644 _images/flatten.gif create mode 100644 _images/fontLib.gif create mode 100644 _images/glyphinterpol.gif create mode 100644 _images/glyphmath_examples_01.gif create mode 100644 _images/glyphmath_examples_02.gif create mode 100644 _images/glyphmath_examples_03.gif create mode 100644 _images/glyphmath_examples_04.gif create mode 100644 _images/glyphmath_examples_05.gif create mode 100644 _images/halftone.gif create mode 100644 _images/logo.gif create mode 100644 _images/logo1.gif create mode 100644 _images/message_mac.jpg create mode 100644 _images/rasteriser.gif create mode 100644 _images/selectfont_fl.jpg create mode 100644 _images/selectglyph_fl.jpg create mode 100644 _images/spike.gif create mode 100644 _images/threshold.gif create mode 100644 _images/ufo.jpg create mode 100644 _sources/api/gString.rst.txt create mode 100644 _sources/api/glifLib.rst.txt create mode 100644 _sources/api/glifLib2.rst.txt create mode 100644 _sources/api/index.rst.txt create mode 100644 _sources/api/interface/all/all.rst.txt create mode 100644 _sources/api/interface/all/dialogs.rst.txt create mode 100644 _sources/api/interface/all/dialogs_default.rst.txt create mode 100644 _sources/api/interface/all/dialogs_fontlab_legacy1.rst.txt create mode 100644 _sources/api/interface/all/dialogs_fontlab_legacy2.rst.txt create mode 100644 _sources/api/interface/all/dialogs_legacy.rst.txt create mode 100644 _sources/api/interface/all/dialogs_mac_vanilla.rst.txt create mode 100644 _sources/api/interface/interface.rst.txt create mode 100644 _sources/api/interface/mac/mac.rst.txt create mode 100644 _sources/api/interface/win/win.rst.txt create mode 100644 _sources/api/misc/arrayTools.rst.txt create mode 100644 _sources/api/misc/bezierTools.rst.txt create mode 100644 _sources/api/misc/misc.rst.txt create mode 100644 _sources/api/misc/speedTestCase.rst.txt create mode 100644 _sources/api/misc/test.rst.txt create mode 100644 _sources/api/objects/index.rst.txt create mode 100644 _sources/api/objects/objectsBase.rst.txt create mode 100644 _sources/api/objects/objectsFF.rst.txt create mode 100644 _sources/api/objects/objectsFL.rst.txt create mode 100644 _sources/api/objects/objectsRF.rst.txt create mode 100644 _sources/api/pens/adapterPens.rst.txt create mode 100644 _sources/api/pens/angledMarginPen.rst.txt create mode 100644 _sources/api/pens/boundsPen.rst.txt create mode 100644 _sources/api/pens/digestPen.rst.txt create mode 100644 _sources/api/pens/filterPen.rst.txt create mode 100644 _sources/api/pens/flPen.rst.txt create mode 100644 _sources/api/pens/marginPen.rst.txt create mode 100644 _sources/api/pens/mathPens.rst.txt create mode 100644 _sources/api/pens/pens.rst.txt create mode 100644 _sources/api/pens/pointPen.rst.txt create mode 100644 _sources/api/pens/quartzPen.rst.txt create mode 100644 _sources/api/pens/reverseContourPointPen.rst.txt create mode 100644 _sources/api/pens/rfUFOPen.rst.txt create mode 100644 _sources/api/plistFromTree.rst.txt create mode 100644 _sources/api/plistlib.rst.txt create mode 100644 _sources/api/test/test.rst.txt create mode 100644 _sources/api/test/test_dialogs.rst.txt create mode 100644 _sources/api/test/test_glifLib.rst.txt create mode 100644 _sources/api/test/test_noneLabUFOReadWrite.rst.txt create mode 100644 _sources/api/test/test_objectsUFO.rst.txt create mode 100644 _sources/api/test/test_pens.rst.txt create mode 100644 _sources/api/test/test_psHints.rst.txt create mode 100644 _sources/api/tools/accentBuilder.rst.txt create mode 100644 _sources/api/tools/fontlabFeatureSplitter.rst.txt create mode 100644 _sources/api/tools/glifExport.rst.txt create mode 100644 _sources/api/tools/glifImport.rst.txt create mode 100644 _sources/api/tools/glyphConstruction.rst.txt create mode 100644 _sources/api/tools/glyphNameSchemes.rst.txt create mode 100644 _sources/api/tools/index.rst.txt create mode 100644 _sources/api/tools/objectDumper.rst.txt create mode 100644 _sources/api/tools/otFeatures.rst.txt create mode 100644 _sources/api/tools/proof.rst.txt create mode 100644 _sources/api/tools/remote.rst.txt create mode 100644 _sources/api/tools/rfPrefs.rst.txt create mode 100644 _sources/api/tools/toolsAll.rst.txt create mode 100644 _sources/api/tools/toolsFL.rst.txt create mode 100644 _sources/api/tools/toolsRF.rst.txt create mode 100644 _sources/api/ufoLib.rst.txt create mode 100644 _sources/api/world.rst.txt create mode 100644 _sources/api/xmlTreeBuilder.rst.txt create mode 100644 _sources/howtos/building_accents.rst.txt create mode 100644 _sources/howtos/fontlab_remote.rst.txt create mode 100644 _sources/howtos/generating_fonts.rst.txt create mode 100644 _sources/howtos/glifnames.rst.txt create mode 100644 _sources/howtos/glyphmath.rst.txt create mode 100644 _sources/howtos/index.rst.txt create mode 100644 _sources/howtos/interpolate.rst.txt create mode 100644 _sources/howtos/lowlevel.rst.txt create mode 100644 _sources/howtos/makeufo.rst.txt create mode 100644 _sources/howtos/ot_features.rst.txt create mode 100644 _sources/howtos/scripting.rst.txt create mode 100644 _sources/howtos/understanding_contours.rst.txt create mode 100644 _sources/howtos/use_lib.rst.txt create mode 100644 _sources/howtos/use_pens.rst.txt create mode 100644 _sources/howtos/use_transformations.rst.txt create mode 100644 _sources/howtos/world.rst.txt create mode 100644 _sources/index.rst.txt create mode 100644 _sources/intro/dialogs.rst.txt create mode 100644 _sources/intro/download.rst.txt create mode 100644 _sources/intro/gettingstarted.rst.txt create mode 100644 _sources/intro/glossary.rst.txt create mode 100644 _sources/intro/history.rst.txt create mode 100644 _sources/intro/index.rst.txt create mode 100644 _sources/intro/install.rst.txt create mode 100644 _sources/intro/intro.rst.txt create mode 100644 _sources/intro/limitations.rst.txt create mode 100644 _sources/intro/links.rst.txt create mode 100644 _sources/intro/summary.rst.txt create mode 100644 _sources/intro/tools.rst.txt create mode 100644 _sources/intro/ufo.rst.txt create mode 100644 _sources/objects/RAnchor.rst.txt create mode 100644 _sources/objects/RComponent.rst.txt create mode 100644 _sources/objects/RContour.rst.txt create mode 100644 _sources/objects/RFont.rst.txt create mode 100644 _sources/objects/RGlyph.rst.txt create mode 100644 _sources/objects/RInfo.rst.txt create mode 100644 _sources/objects/RKerning.rst.txt create mode 100644 _sources/objects/RPoint.rst.txt create mode 100644 _sources/objects/RSegment.rst.txt create mode 100644 _sources/objects/bPoint.rst.txt create mode 100644 _sources/objects/index.rst.txt create mode 100644 _sources/objects/libs.rst.txt create mode 100644 _sources/objects/model.rst.txt create mode 100644 _sources/objects/objects.rst.txt create mode 100644 _sources/objects/pens.rst.txt create mode 100644 _sources/objects/psHints.rst.txt create mode 100644 _sources/objects/psHintsGlyph.rst.txt create mode 100644 _sources/talks/dialogkit.rst.txt create mode 100644 _sources/talks/editors.rst.txt create mode 100644 _sources/talks/index.rst.txt create mode 100644 _sources/talks/interpolation.rst.txt create mode 100644 _sources/talks/python_basics.rst.txt create mode 100644 _sources/talks/session1.rst.txt create mode 100644 _sources/talks/session2.rst.txt create mode 100644 _sources/talks/session3.rst.txt create mode 100644 _sources/talks/session4.rst.txt create mode 100644 _sources/talks/session6.rst.txt create mode 100644 _static/_img/drawmodel.jpg create mode 100644 _static/_img/drawmodel_header.jpg create mode 100644 _static/_img/logo.gif create mode 100644 _static/_img/offdrawmodel_02.gif create mode 100644 _static/_img/offdrawmodel_05.gif create mode 100644 _static/_img/offdrawmodel_07.gif create mode 100644 _static/_img/offdrawmodel_11.gif create mode 100644 _static/_img/offdrawmodel_13.gif create mode 100644 _static/_img/offdrawmodel_17.gif create mode 100644 _static/_img/offdrawmodel_20.gif create mode 100644 _static/_img/offdrawmodel_22.gif create mode 100644 _static/_img/offdrawmodel_26.gif create mode 100644 _static/_img/offdrawmodel_28.gif create mode 100644 _static/_img/offdrawmodel_30.gif create mode 100644 _static/_img/offdrawmodel_34.gif create mode 100644 _static/_img/ondrawmodel_02.gif create mode 100644 _static/_img/ondrawmodel_05.gif create mode 100644 _static/_img/ondrawmodel_07.gif create mode 100644 _static/_img/ondrawmodel_11.gif create mode 100644 _static/_img/ondrawmodel_13.gif create mode 100644 _static/_img/ondrawmodel_17.gif create mode 100644 _static/_img/ondrawmodel_20.gif create mode 100644 _static/_img/ondrawmodel_22.gif create mode 100644 _static/_img/ondrawmodel_26.gif create mode 100644 _static/_img/ondrawmodel_28.gif create mode 100644 _static/_img/ondrawmodel_30.gif create mode 100644 _static/_img/ondrawmodel_34.gif create mode 100644 _static/ajax-loader.gif create mode 100644 _static/basic.css create mode 100644 _static/comment-bright.png create mode 100644 _static/comment-close.png create mode 100644 _static/comment.png create mode 100644 _static/doctools.js create mode 100644 _static/down-pressed.png create mode 100644 _static/down.png create mode 100644 _static/file.png create mode 100644 _static/jquery-3.1.0.js create mode 100644 _static/jquery.js create mode 100644 _static/minus.png create mode 100644 _static/plus.png create mode 100644 _static/pygments.css create mode 100644 _static/robofab.css create mode 100644 _static/robofab.sass create mode 100644 _static/sass2css.py create mode 100644 _static/searchtools.js create mode 100644 _static/underscore-1.3.1.js create mode 100644 _static/underscore.js create mode 100644 _static/up-pressed.png create mode 100644 _static/up.png create mode 100644 _static/websupport.js create mode 100644 api/gString.html create mode 100644 api/glifLib.html create mode 100644 api/glifLib2.html create mode 100644 api/index.html create mode 100644 api/interface/all/all.html create mode 100644 api/interface/all/dialogs.html create mode 100644 api/interface/all/dialogs_default.html create mode 100644 api/interface/all/dialogs_fontlab_legacy1.html create mode 100644 api/interface/all/dialogs_fontlab_legacy2.html create mode 100644 api/interface/all/dialogs_legacy.html create mode 100644 api/interface/all/dialogs_mac_vanilla.html create mode 100644 api/interface/interface.html create mode 100644 api/interface/mac/mac.html create mode 100644 api/interface/win/win.html create mode 100644 api/misc/arrayTools.html create mode 100644 api/misc/bezierTools.html create mode 100644 api/misc/misc.html create mode 100644 api/misc/speedTestCase.html create mode 100644 api/misc/test.html create mode 100644 api/objects/index.html create mode 100644 api/objects/objectsBase.html create mode 100644 api/objects/objectsFF.html create mode 100644 api/objects/objectsFL.html create mode 100644 api/objects/objectsRF.html create mode 100644 api/pens/adapterPens.html create mode 100644 api/pens/angledMarginPen.html create mode 100644 api/pens/boundsPen.html create mode 100644 api/pens/digestPen.html create mode 100644 api/pens/filterPen.html create mode 100644 api/pens/flPen.html create mode 100644 api/pens/marginPen.html create mode 100644 api/pens/mathPens.html create mode 100644 api/pens/pens.html create mode 100644 api/pens/pointPen.html create mode 100644 api/pens/quartzPen.html create mode 100644 api/pens/reverseContourPointPen.html create mode 100644 api/pens/rfUFOPen.html create mode 100644 api/plistFromTree.html create mode 100644 api/plistlib.html create mode 100644 api/test/test.html create mode 100644 api/test/test_dialogs.html create mode 100644 api/test/test_glifLib.html create mode 100644 api/test/test_noneLabUFOReadWrite.html create mode 100644 api/test/test_objectsUFO.html create mode 100644 api/test/test_pens.html create mode 100644 api/test/test_psHints.html create mode 100644 api/tools/accentBuilder.html create mode 100644 api/tools/fontlabFeatureSplitter.html create mode 100644 api/tools/glifExport.html create mode 100644 api/tools/glifImport.html create mode 100644 api/tools/glyphConstruction.html create mode 100644 api/tools/glyphNameSchemes.html create mode 100644 api/tools/index.html create mode 100644 api/tools/objectDumper.html create mode 100644 api/tools/otFeatures.html create mode 100644 api/tools/proof.html create mode 100644 api/tools/remote.html create mode 100644 api/tools/rfPrefs.html create mode 100644 api/tools/toolsAll.html create mode 100644 api/tools/toolsFL.html create mode 100644 api/tools/toolsRF.html create mode 100644 api/ufoLib.html create mode 100644 api/world.html create mode 100644 api/xmlTreeBuilder.html create mode 100644 genindex.html create mode 100644 howtos/building_accents.html create mode 100644 howtos/fontlab_remote.html create mode 100644 howtos/generating_fonts.html create mode 100644 howtos/glifnames.html create mode 100644 howtos/glyphmath.html create mode 100644 howtos/index.html create mode 100644 howtos/interpolate.html create mode 100644 howtos/lowlevel.html create mode 100644 howtos/makeufo.html create mode 100644 howtos/ot_features.html create mode 100644 howtos/scripting.html create mode 100644 howtos/understanding_contours.html create mode 100644 howtos/use_lib.html create mode 100644 howtos/use_pens.html create mode 100644 howtos/use_transformations.html create mode 100644 howtos/world.html create mode 100644 index.html create mode 100644 intro/dialogs.html create mode 100644 intro/download.html create mode 100644 intro/gettingstarted.html create mode 100644 intro/glossary.html create mode 100644 intro/history.html create mode 100644 intro/index.html create mode 100644 intro/install.html create mode 100644 intro/intro.html create mode 100644 intro/limitations.html create mode 100644 intro/links.html create mode 100644 intro/summary.html create mode 100644 intro/tools.html create mode 100644 intro/ufo.html create mode 100644 objects.inv create mode 100644 objects/RAnchor.html create mode 100644 objects/RComponent.html create mode 100644 objects/RContour.html create mode 100644 objects/RFont.html create mode 100644 objects/RGlyph.html create mode 100644 objects/RInfo.html create mode 100644 objects/RKerning.html create mode 100644 objects/RPoint.html create mode 100644 objects/RSegment.html create mode 100644 objects/bPoint.html create mode 100644 objects/index.html create mode 100644 objects/libs.html create mode 100644 objects/model.html create mode 100644 objects/objects.html create mode 100644 objects/pens.html create mode 100644 objects/psHints.html create mode 100644 objects/psHintsGlyph.html create mode 100644 old/credits.html create mode 100644 old/default.css create mode 100644 old/history.html create mode 100644 old/howto/architecture.jpg create mode 100644 old/howto/buildingaccents.html create mode 100644 old/howto/drawingexample.jpg create mode 100644 old/howto/examples/buildaccentsBuilder.py create mode 100644 old/howto/examples/buildaccentsCustom.py create mode 100644 old/howto/examples/gmathFun.py create mode 100644 old/howto/examples/interpolGlyphs.py create mode 100644 old/howto/examples/interpolStraight.py create mode 100644 old/howto/examples/makeufoBinary.py create mode 100644 old/howto/examples/usageBuildaccents.py create mode 100644 old/howto/examples/usageFlremote.py create mode 100644 old/howto/examples/usageGeneratefonts.py create mode 100644 old/howto/examples/usageGlifnames.py create mode 100644 old/howto/examples/usagePens.py create mode 100644 old/howto/examples/usageTransform.py create mode 100644 old/howto/examples/usageWorld.py create mode 100644 old/howto/examples/useDigestPointPen.py create mode 100644 old/howto/examples/useDigestPtStructure.py create mode 100644 old/howto/features.html create mode 100644 old/howto/fontlabremote.html create mode 100644 old/howto/generatefonts.html create mode 100644 old/howto/glifnames.html create mode 100644 old/howto/glyphmath.html create mode 100644 old/howto/hints.html create mode 100644 old/howto/index.html create mode 100644 old/howto/interpolate.html create mode 100644 old/howto/lowlevel.html create mode 100644 old/howto/makeufo.html create mode 100644 old/howto/objectinheritance.jpg create mode 100644 old/howto/scripting.html create mode 100644 old/howto/understandcontours.html create mode 100644 old/howto/usepens.html create mode 100644 old/howto/usethelib.html create mode 100644 old/howto/usetransformations.html create mode 100644 old/howto/world.html create mode 100644 old/img/drawmodel.jpg create mode 100644 old/img/drawmodel_header.jpg create mode 100644 old/img/flatten.gif create mode 100644 old/img/halftone.gif create mode 100644 old/img/logo.gif create mode 100644 old/img/offdrawmodel_02.gif create mode 100644 old/img/offdrawmodel_05.gif create mode 100644 old/img/offdrawmodel_07.gif create mode 100644 old/img/offdrawmodel_11.gif create mode 100644 old/img/offdrawmodel_13.gif create mode 100644 old/img/offdrawmodel_17.gif create mode 100644 old/img/offdrawmodel_20.gif create mode 100644 old/img/offdrawmodel_22.gif create mode 100644 old/img/offdrawmodel_26.gif create mode 100644 old/img/offdrawmodel_28.gif create mode 100644 old/img/offdrawmodel_30.gif create mode 100644 old/img/offdrawmodel_34.gif create mode 100644 old/img/ondrawmodel_02.gif create mode 100644 old/img/ondrawmodel_05.gif create mode 100644 old/img/ondrawmodel_07.gif create mode 100644 old/img/ondrawmodel_11.gif create mode 100644 old/img/ondrawmodel_13.gif create mode 100644 old/img/ondrawmodel_17.gif create mode 100644 old/img/ondrawmodel_20.gif create mode 100644 old/img/ondrawmodel_22.gif create mode 100644 old/img/ondrawmodel_26.gif create mode 100644 old/img/ondrawmodel_28.gif create mode 100644 old/img/ondrawmodel_30.gif create mode 100644 old/img/ondrawmodel_34.gif create mode 100644 old/img/spike.gif create mode 100644 old/img/temptitle.gif create mode 100644 old/img/threshold.gif create mode 100644 old/index.html create mode 100644 old/install.html create mode 100644 old/intro.html create mode 100644 old/limitations.html create mode 100644 old/objects/anchor.html create mode 100644 old/objects/bpoint.html create mode 100644 old/objects/component.html create mode 100644 old/objects/contour.html create mode 100644 old/objects/contours.jpg create mode 100644 old/objects/contours_bpoints.jpg create mode 100644 old/objects/contours_points.jpg create mode 100644 old/objects/contours_segments.jpg create mode 100644 old/objects/contours_segments_points.jpg create mode 100644 old/objects/examples/anchorAttributes.py create mode 100644 old/objects/examples/anchorMethods.py create mode 100644 old/objects/examples/bpointAttributes.py create mode 100644 old/objects/examples/bpointMethods.py create mode 100644 old/objects/examples/componentAttributes.py create mode 100644 old/objects/examples/componentMethods.py create mode 100644 old/objects/examples/contourMethods.py create mode 100644 old/objects/examples/fontAttributes.py create mode 100644 old/objects/examples/fontIterate.py create mode 100644 old/objects/examples/fontMethods.py create mode 100644 old/objects/examples/fontMethodsFL.py create mode 100644 old/objects/examples/glyphAttributes.py create mode 100644 old/objects/examples/glyphMethods.py create mode 100644 old/objects/examples/remapComponent.py create mode 100644 old/objects/examples/segmentAttributes.py create mode 100644 old/objects/examples/segmentMethods.py create mode 100644 old/objects/examples/usageAnchor.py create mode 100644 old/objects/examples/usageBpoint.py create mode 100644 old/objects/examples/usageComponent.py create mode 100644 old/objects/examples/usageContour.py create mode 100644 old/objects/examples/usageFont.py create mode 100644 old/objects/examples/usageGlyph.py create mode 100644 old/objects/examples/usageInfo.py create mode 100644 old/objects/examples/usageKerning.py create mode 100644 old/objects/examples/usageLib.py create mode 100644 old/objects/examples/usagePSHintData.py create mode 100644 old/objects/examples/usagePen.py create mode 100644 old/objects/examples/usagePoint.py create mode 100644 old/objects/examples/usageSegment.py create mode 100644 old/objects/font.html create mode 100644 old/objects/generic.html create mode 100644 old/objects/glyph.html create mode 100644 old/objects/index.html create mode 100644 old/objects/info.html create mode 100644 old/objects/kerning.html create mode 100644 old/objects/lib.html create mode 100644 old/objects/model.html create mode 100644 old/objects/objectModel.jpg create mode 100644 old/objects/pen.html create mode 100644 old/objects/point.html create mode 100644 old/objects/pshints.html create mode 100644 old/objects/pshintsGlyph.html create mode 100644 old/objects/segment.html create mode 100644 old/print.css create mode 100644 old/py2html.css create mode 100644 old/robothon/.afpDeleted32421152 create mode 100644 old/robothon/.afpDeleted33791704 create mode 100644 old/robothon/CONV_CS5_AdobeTypekit-h-lightBG.svg create mode 100644 old/robothon/H_and_co.svg create mode 100644 old/robothon/commercial-r.svg create mode 100644 old/robothon/fonts-by-hco-rgb-300x100.pdf create mode 100644 old/robothon/foosball/test.py create mode 100644 old/robothon/index.html create mode 100644 old/robothon/index_old.html create mode 100644 old/robothon/index_sold_out_2015.html create mode 100644 old/robothon/kabk_logo_rood.png create mode 100644 old/robothon/references.html create mode 100644 old/robothon/robothon.css create mode 100644 old/robothon/robothon09icon.jpg create mode 100644 old/robothon/robothon2015_logo.jpg create mode 100644 old/robothon/robothon2015_logo_2.jpg create mode 100644 old/robothon/th-27_kabk_logo_rood.png create mode 100644 old/robothon/twitter-bird-16x16.png create mode 100644 old/robothon2012/fonts.css create mode 100644 old/robothon2012/img/logo_white.png create mode 100644 old/robothon2012/img/logo_white_blackhole.png create mode 100644 old/robothon2012/img/logo_white_blackhole_fix.png create mode 100644 old/robothon2012/img/logo_white_blackhole_space.png create mode 100644 old/robothon2012/index.html create mode 100644 old/robothon2012/index_webcast.html create mode 100644 old/robothon2012/screen.css create mode 100644 old/styles.css create mode 100644 old/talks/basic.html create mode 100644 old/talks/cent.gif create mode 100644 old/talks/compatibility-scheme_2_01.gif create mode 100644 old/talks/compatibility-scheme_2_02.gif create mode 100644 old/talks/compatibility-scheme_2_03.gif create mode 100644 old/talks/compatibility-scheme_2_04.gif create mode 100644 old/talks/compatibility-scheme_2_05.gif create mode 100644 old/talks/compatibility-scheme_2_06.gif create mode 100644 old/talks/compatibility-scheme_2_07.gif create mode 100644 old/talks/compatibility-scheme_2_08.gif create mode 100644 old/talks/condensor.jpg create mode 100644 old/talks/dialogkit.html create mode 100644 old/talks/examples/aGlyphParent.py create mode 100644 old/talks/examples/allFontsFontInfo.py create mode 100644 old/talks/examples/batchGenerate.py create mode 100644 old/talks/examples/batchInterpolate.py create mode 100644 old/talks/examples/batchSaveAs.py create mode 100644 old/talks/examples/buildingAccents1.py create mode 100644 old/talks/examples/compileGlyph.py create mode 100644 old/talks/examples/cookieCutter.py create mode 100644 old/talks/examples/drawStuffWithPen.py create mode 100644 old/talks/examples/editNameTable.py create mode 100644 old/talks/examples/fileWalker.py create mode 100644 old/talks/examples/floatingPointGlyph.py create mode 100644 old/talks/examples/fontLabRemote.py create mode 100644 old/talks/examples/getSomeGlyphs.py create mode 100644 old/talks/examples/glyphCondensor.py create mode 100644 old/talks/examples/glyphMathOperations.py create mode 100644 old/talks/examples/index.html create mode 100644 old/talks/examples/infoAutonaming.py create mode 100644 old/talks/examples/interpolateFontSeries.py create mode 100644 old/talks/examples/interpolateGlyphs.py create mode 100644 old/talks/examples/interpolateSeries.py create mode 100644 old/talks/examples/interpolateTwoFonts.py create mode 100644 old/talks/examples/iterateContour.py create mode 100644 old/talks/examples/iterateFont.py create mode 100644 old/talks/examples/iterateGlyph.py create mode 100644 old/talks/examples/iteratePoints.py create mode 100644 old/talks/examples/makeFontInfoReport.py create mode 100644 old/talks/examples/mergeTwoFonts.py create mode 100644 old/talks/examples/prepareInterpolGlyph.py create mode 100644 old/talks/examples/printingPen.py create mode 100644 old/talks/examples/remoteEventDemo.py create mode 100644 old/talks/examples/robustBatchGenerate.py create mode 100644 old/talks/examples/setGuideLinesOnAverage.py create mode 100644 old/talks/examples/showEncoding.py create mode 100644 old/talks/examples/showNamingRecords.py create mode 100644 old/talks/examples/sillyRasteriser.py create mode 100644 old/talks/examples/someFontInfoAttributes.py create mode 100644 old/talks/examples/someFontInfoAttributes2.py create mode 100644 old/talks/examples/someGlyphAttributes.py create mode 100644 old/talks/examples/someGlyphAttributes2.py create mode 100644 old/talks/examples/someNameTableAttrs.py create mode 100644 old/talks/examples/test.py create mode 100644 old/talks/examples/transformGlyph.py create mode 100644 old/talks/examples/usingCoreGraphicsOSX.py create mode 100644 old/talks/examples/variousHintFunctions.py create mode 100644 old/talks/examples/workWithKerning1.py create mode 100644 old/talks/examples/workWithKerning2.py create mode 100644 old/talks/examples/workWithKerning3.py create mode 100644 old/talks/examples/workWithKerning4.py create mode 100644 old/talks/exportmenu.gif create mode 100644 old/talks/glyphMath.gif create mode 100644 old/talks/glyphinterpol.gif create mode 100644 old/talks/glyphmath_examples_01.gif create mode 100644 old/talks/glyphmath_examples_02.gif create mode 100644 old/talks/glyphmath_examples_03.gif create mode 100644 old/talks/glyphmath_examples_04.gif create mode 100644 old/talks/glyphmath_examples_05.gif create mode 100644 old/talks/index.html create mode 100644 old/talks/introduction.html create mode 100644 old/talks/printBooklet.html create mode 100644 old/talks/printConferenceBooklet.html create mode 100644 old/talks/printNoneLab.html create mode 100644 old/talks/rasteriser.gif create mode 100644 old/talks/robofab_session1.html create mode 100644 old/talks/robofab_session2.html create mode 100644 old/talks/robofab_session3.html create mode 100644 old/talks/robofab_session4.html create mode 100644 old/talks/robofab_session5.html create mode 100644 old/talks/robofab_session6.html create mode 100644 old/talks/robothon06_logo.gif create mode 100644 old/talks/ufo.jpg create mode 100644 old/talks09/UFO_print.jpg create mode 100644 old/talks09/basic.html create mode 100644 old/talks09/cent.gif create mode 100644 old/talks09/compatibility-scheme_2_01.gif create mode 100644 old/talks09/compatibility-scheme_2_02.gif create mode 100644 old/talks09/compatibility-scheme_2_03.gif create mode 100644 old/talks09/compatibility-scheme_2_04.gif create mode 100644 old/talks09/compatibility-scheme_2_05.gif create mode 100644 old/talks09/compatibility-scheme_2_06.gif create mode 100644 old/talks09/compatibility-scheme_2_07.gif create mode 100644 old/talks09/compatibility-scheme_2_08.gif create mode 100644 old/talks09/condensor.jpg create mode 100644 old/talks09/dialogkit.html create mode 100644 old/talks09/examples/aGlyphParent.py create mode 100644 old/talks09/examples/allFontsFontInfo.py create mode 100644 old/talks09/examples/batchGenerate.py create mode 100644 old/talks09/examples/batchInterpolate.py create mode 100644 old/talks09/examples/batchSaveAs.py create mode 100644 old/talks09/examples/buildingAccents1.py create mode 100644 old/talks09/examples/compileGlyph.py create mode 100644 old/talks09/examples/cookieCutter.py create mode 100644 old/talks09/examples/drawStuffWithPen.py create mode 100644 old/talks09/examples/editNameTable.py create mode 100644 old/talks09/examples/fileWalker.py create mode 100644 old/talks09/examples/floatingPointGlyph.py create mode 100644 old/talks09/examples/fontLabRemote.py create mode 100644 old/talks09/examples/getSomeGlyphs.py create mode 100644 old/talks09/examples/glyphCondensor.py create mode 100644 old/talks09/examples/glyphMathOperations.py create mode 100644 old/talks09/examples/infoAutonaming.py create mode 100644 old/talks09/examples/interpolateFontSeries.py create mode 100644 old/talks09/examples/interpolateGlyphs.py create mode 100644 old/talks09/examples/interpolateSeries.py create mode 100644 old/talks09/examples/interpolateTwoFonts.py create mode 100644 old/talks09/examples/iterateContour.py create mode 100644 old/talks09/examples/iterateFont.py create mode 100644 old/talks09/examples/iterateGlyph.py create mode 100644 old/talks09/examples/iteratePoints.py create mode 100644 old/talks09/examples/makeFontInfoReport.py create mode 100644 old/talks09/examples/mergeTwoFonts.py create mode 100644 old/talks09/examples/prepareInterpolGlyph.py create mode 100644 old/talks09/examples/printingPen.py create mode 100644 old/talks09/examples/remoteEventDemo.py create mode 100644 old/talks09/examples/robustBatchGenerate.py create mode 100644 old/talks09/examples/setGuideLinesOnAverage.py create mode 100644 old/talks09/examples/showEncoding.py create mode 100644 old/talks09/examples/showNamingRecords.py create mode 100644 old/talks09/examples/sillyRasteriser.py create mode 100644 old/talks09/examples/someFontInfoAttributes.py create mode 100644 old/talks09/examples/someFontInfoAttributes2.py create mode 100644 old/talks09/examples/someGlyphAttributes.py create mode 100644 old/talks09/examples/someGlyphAttributes2.py create mode 100644 old/talks09/examples/someNameTableAttrs.py create mode 100644 old/talks09/examples/test.py create mode 100644 old/talks09/examples/transformGlyph.py create mode 100644 old/talks09/examples/usingCoreGraphicsOSX.py create mode 100644 old/talks09/examples/variousHintFunctions.py create mode 100644 old/talks09/examples/workWithKerning1.py create mode 100644 old/talks09/examples/workWithKerning2.py create mode 100644 old/talks09/examples/workWithKerning3.py create mode 100644 old/talks09/examples/workWithKerning4.py create mode 100644 old/talks09/exportmenu.gif create mode 100644 old/talks09/fabPythonBasics.html create mode 100644 old/talks09/glyphMath.gif create mode 100644 old/talks09/glyphinterpol.gif create mode 100644 old/talks09/glyphmath_examples_01.gif create mode 100644 old/talks09/glyphmath_examples_02.gif create mode 100644 old/talks09/glyphmath_examples_03.gif create mode 100644 old/talks09/glyphmath_examples_04.gif create mode 100644 old/talks09/glyphmath_examples_05.gif create mode 100644 old/talks09/index.html create mode 100644 old/talks09/printBooklet.html create mode 100644 old/talks09/rasteriser.gif create mode 100644 old/talks09/robofab_session1.html create mode 100644 old/talks09/robofab_session2.html create mode 100644 old/talks09/robofab_session3.html create mode 100644 old/talks09/robofab_session4.html create mode 100644 old/talks09/robofab_session5.html create mode 100644 old/talks09/robofab_session6.html create mode 100644 old/talks09/robothon06_logo.gif create mode 100644 old/talks09/ufo.jpg create mode 100644 old/tools/askstring_mac.jpg create mode 100644 old/tools/askyesnocancel_mac.jpg create mode 100644 old/tools/dialogs.html create mode 100644 old/tools/findglyph_fl.jpg create mode 100644 old/tools/index.html create mode 100644 old/tools/message_mac.jpg create mode 100644 old/tools/selectfont_fl.jpg create mode 100644 old/tools/selectglyph_fl.jpg create mode 100644 old/tools/tool.html create mode 100644 old/ufo/glif.html create mode 100644 old/ufo/index.html create mode 100644 old/ufo/pen.html create mode 100644 old/ufo/plist.html create mode 100644 old/ufo/specification.html create mode 100644 old/ufo/xmltext.jpg create mode 100644 py-modindex.html create mode 100644 search.html create mode 100644 searchindex.js create mode 100644 talks/dialogkit.html create mode 100644 talks/editors.html create mode 100644 talks/index.html create mode 100644 talks/interpolation.html create mode 100644 talks/python_basics.html create mode 100644 talks/session1.html create mode 100644 talks/session2.html create mode 100644 talks/session3.html create mode 100644 talks/session4.html create mode 100644 talks/session6.html diff --git a/_downloads/RAnchor_00.py b/_downloads/RAnchor_00.py new file mode 100644 index 0000000..82a9495 --- /dev/null +++ b/_downloads/RAnchor_00.py @@ -0,0 +1,9 @@ +# robofab manual +# Anchor object +# usage examples + +f = CurrentFont() + +for g in f: + if len(g.anchors) > 0: + print g, g.anchors diff --git a/_downloads/RAnchor_01.py b/_downloads/RAnchor_01.py new file mode 100644 index 0000000..16a3eac --- /dev/null +++ b/_downloads/RAnchor_01.py @@ -0,0 +1,9 @@ +# robofab manual +# Anchor object +# attribute examples + +g = CurrentGlyph() + +if len(g.anchors) > 0: + for a in g.anchors: + print a.position \ No newline at end of file diff --git a/_downloads/RComponent_00.py b/_downloads/RComponent_00.py new file mode 100644 index 0000000..f5541aa --- /dev/null +++ b/_downloads/RComponent_00.py @@ -0,0 +1,10 @@ +# the easiest way to get to a component +# is to get one from a glyph + +from robofab.world import CurrentFont + +f = CurrentFont() +g = f['adieresis'] + +for c in g.components: + print c diff --git a/_downloads/RComponent_01.py b/_downloads/RComponent_01.py new file mode 100644 index 0000000..b8e9fe2 --- /dev/null +++ b/_downloads/RComponent_01.py @@ -0,0 +1,12 @@ +# robofab manual +# Component object +# attribute examples + +print f['adieresis'].components[0].baseGlyph +print f['adieresis'].components[1].baseGlyph + +# move the component in the base glyph +f['adieresis'].components[1].offset = (100,100) + +# scale the component in the base glyph +f['adieresis'].components[0].scale = (.5, .25) diff --git a/_downloads/RContour_00.py b/_downloads/RContour_00.py new file mode 100644 index 0000000..8f5871e --- /dev/null +++ b/_downloads/RContour_00.py @@ -0,0 +1,9 @@ +# robofab manual +# Contour object +# usage examples + +# take a glyph (one with outlines obviously) +c = CurrentGlyph() + +# get to contours by index: +print c[0] \ No newline at end of file diff --git a/_downloads/RFont_00.py b/_downloads/RFont_00.py new file mode 100644 index 0000000..33b9248 --- /dev/null +++ b/_downloads/RFont_00.py @@ -0,0 +1,17 @@ +# robofab manual +# Font object +# Usage examples + +# start using the current font +from robofab.world import CurrentFont +f = CurrentFont() + +# get a clean, empty new font object, +# appropriate for the current environment +f = robofab.world.RFont() + +# get an open dialog and start a new font +f = OpenFont() + +# open the font at path +f = OpenFont(path) \ No newline at end of file diff --git a/_downloads/RFont_01.py b/_downloads/RFont_01.py new file mode 100644 index 0000000..10669de --- /dev/null +++ b/_downloads/RFont_01.py @@ -0,0 +1,8 @@ +# robofab manual +# Font object +# Iterate through the font object to get to the glyphs. + +f = CurrentFont() + +for glyph in f: + print glyph.name \ No newline at end of file diff --git a/_downloads/RFont_02.py b/_downloads/RFont_02.py new file mode 100644 index 0000000..48d82ea --- /dev/null +++ b/_downloads/RFont_02.py @@ -0,0 +1,8 @@ +# cache the kerning object for speed + +from robofab.world import CurrentFont + +f = CurrentFont() + +cachedKerning = f.kerning +# continue to use cachedKerning, not f.kerning. \ No newline at end of file diff --git a/_downloads/RFont_03.py b/_downloads/RFont_03.py new file mode 100644 index 0000000..7a01eee --- /dev/null +++ b/_downloads/RFont_03.py @@ -0,0 +1,17 @@ +# robofab manual +# Font object +# attribute examples +# Most useful attributes of RFont +# are actually stored in RFont.info + +f = CurrentFont() +print f.info.unitsPerEm + +# kerning data is available in the kerning object: +print f.kerning + +# len() gives you the "length" of the font, i.e. the number of glyphs +print "glyphs in this font:", len(f) + +# treat a font object as a dictionary to get to the glyphs +print f["A"] diff --git a/_downloads/RFont_04.py b/_downloads/RFont_04.py new file mode 100644 index 0000000..151d0f2 --- /dev/null +++ b/_downloads/RFont_04.py @@ -0,0 +1,12 @@ +# robofab manual +# Font object +# method examples + +from robofab.world import CurrentFont +f = CurrentFont() + +# the keys() method returns a list of glyphnames: +print f.keys() + +# find unicodes for each glyph by using the postscript name: +f.autoUnicodes() \ No newline at end of file diff --git a/_downloads/RFont_05.py b/_downloads/RFont_05.py new file mode 100644 index 0000000..c8995ff --- /dev/null +++ b/_downloads/RFont_05.py @@ -0,0 +1,12 @@ +# robofab manual +# Font object +# method examples, available in FontLab + +from robofab.world import CurrentFont +f = CurrentFont() + +# the keys() method returns a list of glyphnames: +print f.selection + +# generate font binaries +f.generate('otfcff') diff --git a/_downloads/RGlyph_00.py b/_downloads/RGlyph_00.py new file mode 100644 index 0000000..03337a4 --- /dev/null +++ b/_downloads/RGlyph_00.py @@ -0,0 +1,22 @@ +# robofab manual +# Glyph object +# Usage examples + +# start using the current font +from robofab.world import CurrentGlyph +g = CurrentGlyph() + +# suppose you've done the right imports +# different ways of creating glyphs +# a new empty glyph object +g = robofab.world.RGlyph() + +# a new empty fontlab glyph object +g = robofab.objects.objectsFL.RGlyph() + +# a new empty robofab glyph object +g = robofab.objects.objectsRF.RGlyph() + +# the easiest way to get a new glyph +# is to ask a font to make you one: +g = aFontObject[glyphName] diff --git a/_downloads/RGlyph_01.py b/_downloads/RGlyph_01.py new file mode 100644 index 0000000..922db90 --- /dev/null +++ b/_downloads/RGlyph_01.py @@ -0,0 +1,28 @@ +# robofab manual +# Glyph object +# attribute examples + +from robofab.world import CurrentFont, CurrentGlyph +f = CurrentFont() + +# create a glyph object by asking the font +g = f["Adieresis"] + +# alternatively, create a glyph object for the current glyph +g = CurrentGlyph() + +# get the width +print g.width + +# get the name +print g.name + +# a list of unicode values for this glyph. Can be more than 1! +print g.unicodes + +# set the width +g.width = 1000 +print g.width + +# get the number of contours in a glyph by getting its length +print len(g) \ No newline at end of file diff --git a/_downloads/RGlyph_02.py b/_downloads/RGlyph_02.py new file mode 100644 index 0000000..0efb709 --- /dev/null +++ b/_downloads/RGlyph_02.py @@ -0,0 +1,12 @@ +# robofab manual +# Glyph object +# method examples + +# get a glyph object from a font +f = CurrentFont() +g = f["A"] +print g + +# move the glyph 10 units to the right, and 200 units up: +g = f["a"] +g.move((10, 200)) \ No newline at end of file diff --git a/_downloads/RGlyph_03.py b/_downloads/RGlyph_03.py new file mode 100644 index 0000000..3afb527 --- /dev/null +++ b/_downloads/RGlyph_03.py @@ -0,0 +1,21 @@ +# robofab manual +# Glyph object +# method examples + +# In FontLab the baseglyph of a component can't be changed easily. +# This assumes that there will only be +# one component that needs to be remapped. + +def remapComponent(glyph, oldBaseGlyph, newBaseGlyph): + foundComponent = None + for component in glyph.components: + if component.baseGlyph = oldBaseGlyph: + foundComponent = component + break + if foundComponent is None: + return + offset = foundComponent.offset + scale = foundComponent.scale + glyph.removeComponent(component) + glyph.appendComponent(newBaseGlyph, offset=offset, scale=scale) + diff --git a/_downloads/RInfo_00.py b/_downloads/RInfo_00.py new file mode 100644 index 0000000..32a4e1f --- /dev/null +++ b/_downloads/RInfo_00.py @@ -0,0 +1,21 @@ +# robofab manual +# Info object +# usage examples + +from robofab.world import CurrentFont + +f = CurrentFont() +print f.info.postscriptFullName +print f.info.openTypeNameDesigner + +f.info.openTypeNameDesigner = "Jan van Krimpen" +print f.info.openTypeNameDesigner +print f.info.openTypeOS2VendorID +print f.info.unitsPerEm +print f.info.xHeight +print f.info.openTypeNameLicenseURL + +# but you can set the values as well +f.info.postscriptUniqueID = 4309359 +f.info.openTypeNameDesigner = "Eric Gill" + diff --git a/_downloads/RKerning_00.py b/_downloads/RKerning_00.py new file mode 100644 index 0000000..52a448e --- /dev/null +++ b/_downloads/RKerning_00.py @@ -0,0 +1,11 @@ +# robofab manual +# Kerning object +# usage examples + +f = CurrentFont() +print f.kerning + +# getting a value from the kerning dictionary +print f.kerning[('V', 'A')] +print f.kerning[('T', 'X')] +print f.kerning.keys() diff --git a/_downloads/RLib_00.py b/_downloads/RLib_00.py new file mode 100644 index 0000000..87257a5 --- /dev/null +++ b/_downloads/RLib_00.py @@ -0,0 +1,9 @@ +# robofab manual +# Lib object +# attribute examples + +# RFont objects have a lib: +print aFont.lib + +# content of the lib of a font exported from RoboFog +print f.lib.keys() \ No newline at end of file diff --git a/_downloads/RPoint_00.py b/_downloads/RPoint_00.py new file mode 100644 index 0000000..544fc0e --- /dev/null +++ b/_downloads/RPoint_00.py @@ -0,0 +1,13 @@ +# robofab manual +# Point object +# usage examples + +contour = CurrentGlyph()[0] +print contour.points[0] + +from random import randint +for p in contour.points: + p.x += randint(-10,10) + p.y += randint(-10,10) + +contour.update() \ No newline at end of file diff --git a/_downloads/RSegment_00.py b/_downloads/RSegment_00.py new file mode 100644 index 0000000..ffc5f0c --- /dev/null +++ b/_downloads/RSegment_00.py @@ -0,0 +1,10 @@ +# robofab manual +# Segment object +# usage examples + +f = OpenFont() + +for g in f: + for contour in g: + for segment in contour: + print segment diff --git a/_downloads/RSegment_01.py b/_downloads/RSegment_01.py new file mode 100644 index 0000000..0767af7 --- /dev/null +++ b/_downloads/RSegment_01.py @@ -0,0 +1,16 @@ +# robofab manual +# Segment object +# attribute examples + +f = OpenFont() + +for g in f: + for contour in g: + for segment in contour: + print len(segment) + print segment.type + print segment.smooth + print segment.points + print segment.onCurve + print segment.offCurve + print segment.selected diff --git a/_downloads/RSegment_02.py b/_downloads/RSegment_02.py new file mode 100644 index 0000000..accc85e --- /dev/null +++ b/_downloads/RSegment_02.py @@ -0,0 +1,10 @@ +# robofab manual +# Segment object +# method examples + +f = OpenFont() + +for g in f: + for contour in g: + for segment in contour: + segment.move((50, 25)) diff --git a/_downloads/bPoint_00.py b/_downloads/bPoint_00.py new file mode 100644 index 0000000..b14f891 --- /dev/null +++ b/_downloads/bPoint_00.py @@ -0,0 +1,7 @@ +# robofab manual +# bPoint object +# Usage examples + +g = CurrentGlyph() +for aPt in g[0].bPoints: + print aPt diff --git a/_downloads/bPoint_01.py b/_downloads/bPoint_01.py new file mode 100644 index 0000000..27da500 --- /dev/null +++ b/_downloads/bPoint_01.py @@ -0,0 +1,8 @@ +# robofab manual +# bPoint object +# Attribute examples + +g = CurrentGlyph() + +for aPt in g[0].bPoints: + print aPt.bcpIn, aPt.bcpOut, aPt.anchor diff --git a/_downloads/buildingAccents_00.py b/_downloads/buildingAccents_00.py new file mode 100644 index 0000000..b033954 --- /dev/null +++ b/_downloads/buildingAccents_00.py @@ -0,0 +1,12 @@ +# robofab manual +# Buildingaccents howto +# usage examples + +from robofab.world import CurrentFont + +f = CurrentFont() +f.newGlyph("aacute") +f["aacute"].appendComponent("a") +f["aacute"].appendComponent("acute", (200, 0)) +f["aacute"].width = f["a"].width +f.update() \ No newline at end of file diff --git a/_downloads/buildingAccents_01.py b/_downloads/buildingAccents_01.py new file mode 100644 index 0000000..3123f93 --- /dev/null +++ b/_downloads/buildingAccents_01.py @@ -0,0 +1,32 @@ +# robofab manual +# Buildingaccents howto +# AccentBuilder examples + +from robofab.world import CurrentFont +from robofab.accentBuilder import AccentTools, buildRelatedAccentList + +font = CurrentFont() + +# a list of accented glyphs that you want to build +myList = ['Aacute', 'aacute'] + +# search for glyphs related to glyphs in myList and add them to myList +myList = buildRelatedAccentList(font, myList)+myList + +# start the class +at = AccentTools(font, myList) + +# clear away any anchors that exist (this is optional) +at.clearAnchors() + +# add necessary anchors if you want to +at.buildAnchors(ucXOffset=20, ucYOffset=40, lcXOffset=15, lcYOffset=30) + +# print a report of any errors that occured +at.printAnchorErrors() + +# build the accented glyphs if you want to +at.buildAccents() + +# print a report of any errors that occured +at.printAccentErrors() \ No newline at end of file diff --git a/_downloads/buildingAccents_02.py b/_downloads/buildingAccents_02.py new file mode 100644 index 0000000..2936367 --- /dev/null +++ b/_downloads/buildingAccents_02.py @@ -0,0 +1,56 @@ +# robofab manual +# Buildingaccents howto +# attribute examples + +# a script to generate all necessary accented characters. +# this assumes all anchor points are set correctly. +# including doublelayer accents. so, add anchorpoints +# on the accents too! +# (c) evb + +from robofab.world import CurrentFont +from robofab.tools.toolsAll import readGlyphConstructions + +f = CurrentFont() + +import string + +theList = [ + # caps + 'AEacute', + 'AEmacron', + 'Aacute', + 'Abreve', + # add all the accents you want in this list +] + +con = readGlyphConstructions() +theList.sort() + +def accentify(f, preflight=False): + print 'start accentification', f.info.fullName + slots = con.keys() + slots.sort() + for k in theList: + if k[-3:] in [".sc"]: + isSpecial = True + tag = k[-3:] + name = k[:-3] + else: + isSpecial = False + tag = "" + name = k + parts = con.get(name, None) + if parts is None: + print k, "not defined?" + continue + base = parts[0] + accents = parts[1:] + f.generateGlyph(k, preflight=preflight) + f[k].mark = 100 + randint(-20, 20) + f[k].autoUnicodes() + f[k].update() + f.update() + +accentify(f) +print 'done' diff --git a/_downloads/fontlabRemote_00.py b/_downloads/fontlabRemote_00.py new file mode 100644 index 0000000..77d794e --- /dev/null +++ b/_downloads/fontlabRemote_00.py @@ -0,0 +1,2 @@ +# start the remote stuff in FontLab +import robofab.tools.remote diff --git a/_downloads/fontlabRemote_01.py b/_downloads/fontlabRemote_01.py new file mode 100644 index 0000000..e28f135 --- /dev/null +++ b/_downloads/fontlabRemote_01.py @@ -0,0 +1,3 @@ +# first, try a bit of python code +from robofab.tools.remote import runFontLabRemote +print runFontLabRemote("print 1+1") \ No newline at end of file diff --git a/_downloads/fontlabRemote_02.py b/_downloads/fontlabRemote_02.py new file mode 100644 index 0000000..1bba9aa --- /dev/null +++ b/_downloads/fontlabRemote_02.py @@ -0,0 +1,7 @@ +from robofab.tools.remote import transmitGlyph + +# Pick a UFO font: +f = OpenFont() + +# one to beam up, Scotty! +transmitGlyph(f['n']) diff --git a/_downloads/fontlabRemote_03.py b/_downloads/fontlabRemote_03.py new file mode 100644 index 0000000..7deaa5f --- /dev/null +++ b/_downloads/fontlabRemote_03.py @@ -0,0 +1,49 @@ +# robofab manual +# Fontlabremote howto +# usage examples + +#FLM: Remove overlap from Remote Glyph. + +from robofab.world import OpenFont +from robofab.tools.remote import transmitGlyph, receiveGlyph, +runFontLabRemote + +# Pick a UFO font: +f = OpenFont() + +print "Number of contours before", len(f['A']) + +# call FontLab to make a new font +startNewFontCode = """from robofab.world import NewFont +f = NewFont() +f.info.fullName = 'Temporary Font generated by RoboFab Remote'""" + +print runFontLabRemote(startNewFontCode) + +# send a glyph to FontLab, +# it will be inserted in the CurrentFont. +transmitGlyph(f['A']) +f.removeGlyph('A') + +# send instructions to remove overlap for this glyph +overlapCode = """from robofab.world import CurrentFont +from robofab.tools.remote import transmitGlyph +f = CurrentFont() +f["A"].removeOverlap() +f.update() +transmitGlyph(f['A']) +""" + +# send the code and catch the output +x = runFontLabRemote(overlapCode) +# interpret the output +receiveGlyph(x, f) +print "Number of contours after: ", len(f['A']) + +# send instructions to FontLab to close the font again. +closeFontCode = """from robofab.world import CurrentFont +f = CurrentFont() +f.close(None) +""" +print runFontLabRemote(closeFontCode) +print 'done!' diff --git a/_downloads/generatingFonts_00.py b/_downloads/generatingFonts_00.py new file mode 100644 index 0000000..d29bf72 --- /dev/null +++ b/_downloads/generatingFonts_00.py @@ -0,0 +1,12 @@ +# robofab manual +# Generatefonts howto +# usage examples + +import os.path +from robofab.world import CurrentFont + +font = CurrentFont() +path = font.path +dir, fileName = os.path.split(path) +path = os.sep.join([dir, font.info.fullName]) +font.generate('mactype1', path) diff --git a/_downloads/glifNames_00.py b/_downloads/glifNames_00.py new file mode 100644 index 0000000..074ea4a --- /dev/null +++ b/_downloads/glifNames_00.py @@ -0,0 +1,21 @@ +# robofab manual +# Glifnames howto +# glyphNameToShortFileName examples + +# examples of glyphname to glif name transformations +from robofab.tools.glyphNameSchemes import glyphNameToShortFileName + +# a short name +print glyphNameToShortFileName("accent", None) + +# a short name, starting with capital letter +print glyphNameToShortFileName("Accent", None) + +# a really long name - note the hexadecimal hash at the end +print glyphNameToShortFileName("this_is_a_very_long_glyph_name.altswash2", None) + +# a name with a period in it, 1 +print glyphNameToShortFileName("a.alt", None) + +# a name with a period in it, 2 +print glyphNameToShortFileName(".notdef", None) diff --git a/_downloads/glyphMath_00.py b/_downloads/glyphMath_00.py new file mode 100644 index 0000000..cf03515 --- /dev/null +++ b/_downloads/glyphMath_00.py @@ -0,0 +1,28 @@ +# robofab manual +# Glyphmath howto +# Fun examples + +#FLM: Fun with GlyphMath + +# this example is meant to run with the RoboFab Demo Font +# as the Current Font. So, if you're doing this in FontLab +# import the Demo Font UFO first. + +from robofab.world import CurrentFont +from random import random + +f = CurrentFont() +condensedLight = f["a#condensed_light"] +wideLight = f["a#wide_light"] +wideBold = f["a#wide_bold"] + +diff = wideLight - condensedLight + +destination = f.newGlyph("a#deltaexperiment") +destination.clear() +x = wideBold + (condensedLight-wideLight)*random() + +destination.appendGlyph( x) +destination.width = x.width + +f.update() \ No newline at end of file diff --git a/_downloads/interpol_00.py b/_downloads/interpol_00.py new file mode 100644 index 0000000..883e3b6 --- /dev/null +++ b/_downloads/interpol_00.py @@ -0,0 +1,10 @@ +# robothon06 +# interpolate two glyphs in the same font + +from robofab.world import CurrentFont + +f = CurrentFont() +factor = 0.5 + +f["C"].interpolate(factor, f["A"], f["B"]) +f["C"].update() \ No newline at end of file diff --git a/_downloads/interpol_01.py b/_downloads/interpol_01.py new file mode 100644 index 0000000..1ead04d --- /dev/null +++ b/_downloads/interpol_01.py @@ -0,0 +1,14 @@ +# robothon06 +# interpolate two glyphs in the same font a bunch of times + +from robofab.world import CurrentFont + +f = CurrentFont() + +for i in range(0, 10): + factor = i*.1 + name = "result_%f"%factor + print "interpolating", name + f[name].interpolate(factor, f["A"], f["B"]) + +f.update() \ No newline at end of file diff --git a/_downloads/interpol_02.py b/_downloads/interpol_02.py new file mode 100644 index 0000000..e81bd2b --- /dev/null +++ b/_downloads/interpol_02.py @@ -0,0 +1,36 @@ +# robothon06 + +from robofab.world import CurrentFont + +# We need to import a class with a different +# implementation for the glyph object. +# It looks a bit odd, but this is how it is done +from robofab.objects.objectsRF import RGlyph as _RGlyph + +f = CurrentFont() + +# pick two compatible glyphs as masters +m1 = f["A"] +m2 = f["B"] + +# make a new glyph object from this other glyph class +g = _RGlyph() + +# interpolation factor which is bound to make floats +oddFactor = 0.2382345 + +# go! +g.interpolate(oddFactor, m1, m2) + +# let's have a look at the raw results +for contour in g: + for pt in contour.points: + print "float", pt.x, pt.y + +# a glyph can round itself off: +g.round() + +# and then it looks like integers again +for contour in g: + for pt in contour.points: + print "integer", pt.x, pt.y diff --git a/_downloads/interpol_03.py b/_downloads/interpol_03.py new file mode 100644 index 0000000..1a1654f --- /dev/null +++ b/_downloads/interpol_03.py @@ -0,0 +1,5 @@ +# see if "A" and "B" can interpolate +from robofab.world import CurrentFont +f = CurrentFont() +a = f["a"] +print a.isCompatible(f["b"], False) diff --git a/_downloads/interpol_04.py b/_downloads/interpol_04.py new file mode 100644 index 0000000..e9a183b --- /dev/null +++ b/_downloads/interpol_04.py @@ -0,0 +1,6 @@ +# see if "A" and "B" can interpolate +# and find out what's wrong if you can +from robofab.world import CurrentFont +f = CurrentFont() +a = f["a"] +print a.isCompatible(f["b"], True) diff --git a/_downloads/interpol_05.py b/_downloads/interpol_05.py new file mode 100644 index 0000000..ae6c086 --- /dev/null +++ b/_downloads/interpol_05.py @@ -0,0 +1,16 @@ +# robothon06 +# prepare glyph for interpolation +# move startpoints +# fix directions +# fix contour order + +from robofab.world import CurrentFont + +f = CurrentFont() +glyph = f["A"] + +glyph.autoContourOrder() +glyph.correctDirection() +for c in glyph.contours: + c.autoStartSegment() +glyph.update() diff --git a/_downloads/interpol_06.py b/_downloads/interpol_06.py new file mode 100644 index 0000000..d91b44d --- /dev/null +++ b/_downloads/interpol_06.py @@ -0,0 +1,22 @@ +# robothon06 +# interpolate two fonts + +from robofab.world import SelectFont, NewFont +from robofab.interface.all.dialogs import AskString + +font1 = SelectFont("Select font 1") +font2 = SelectFont("Select font 2") + +value = AskString("What percentage?") +value = int(value) * .01 + +destination = NewFont() + +# this interpolates the glyphs +destination.interpolate(value, font1, font2, doProgress=True) + +# this interpolates the kerning +# comment this line out of you're just testing +destination.kerning.interpolate(font1.kerning, font2.kerning, value) + +destination.update() \ No newline at end of file diff --git a/_downloads/interpol_07.py b/_downloads/interpol_07.py new file mode 100644 index 0000000..121009b --- /dev/null +++ b/_downloads/interpol_07.py @@ -0,0 +1,37 @@ +# glyphmath example, using glyphs in math +# in the test font: two interpolatable, different glyphs +# on positions A and B. + +from robofab.world import CurrentFont +f = CurrentFont() + +# glyphmath +a = f["A"] +b = f["B"] + +# multiply works as scaling up +d = a * 2 +# or +d = 2 * a + +# note: as of robofab svn version 200, +# the "as" argument in insertGlyph has changed to "name" +f.insertGlyph(d, name="A.A_times_2") + +# division works as scaling down +d = a / 2 +f.insertGlyph(d, name="A.A_divide_2") + +# addition: add coordinates of each point +d = a + b +f.insertGlyph(d, name="A.A_plus_B") + +# subtraction: subtract coordinates of each point +d = a - b +f.insertGlyph(d, name="A.A_minus_B") + +# combination: interpolation! +d = a + .5 * (b-a) +f.insertGlyph(d, name="A.A_interpolate_B") + +f.update() \ No newline at end of file diff --git a/_downloads/interpol_08.py b/_downloads/interpol_08.py new file mode 100644 index 0000000..83cc873 --- /dev/null +++ b/_downloads/interpol_08.py @@ -0,0 +1,38 @@ +# robothon06 +# interpolate two fonts with a series of factors. +# for each factor create a new font file. + +import os +from robofab.world import SelectFont, NewFont +from robofab.interface.all.dialogs import AskString, GetFolder + +font1 = SelectFont("Select font 1") +font2 = SelectFont("Select font 2") +where = GetFolder("Select a folder to save the interpolations") + +instances = [ + ("Light", 0), + ("NotTooLight", 0.25), + ("Regular", 0.5), + ("Demi", 0.75), + ("Medium", 1), +] + +for thing in instances: + name, value = thing + print "generating", name, value + dst = NewFont() + # this interpolates the glyphs + dst.interpolate(value, font1, font2, doProgress=True) + # this interpolates the kerning + # comment this line out of you're just testing + #dst.kerning.interpolate(font1.kerning, font2.kerning, value) + dst.info.familyName = "MyBigFamily" + dst.info.styleName = name + dst.info.autoNaming() + dst.update() + fileName = dst.info.familyName + "-" + dst.info.styleName + ".vfb" + path = os.path.join(where, fileName) + print 'saving at', path + dst.save(path) + dst.close() diff --git a/_downloads/interpol_09.py b/_downloads/interpol_09.py new file mode 100644 index 0000000..f63b2eb --- /dev/null +++ b/_downloads/interpol_09.py @@ -0,0 +1,25 @@ +# robothon06 +# Get started with a condensed if you have a regular and a bold: +# seperate x, y interpolation to make stems fatter +# then scaling to reduce width +# stems will get their original thickness + +from robofab.world import CurrentFont +f = CurrentFont() + +# these are measurements you have to take +# from your font. The width of a stem. + +lightStem = 106 +fatStem = 200 + +for i in range(0, 10): + factor = (i * 0.1, 0) + name = "result_%f" % factor[0] + scale = float(lightStem) / (lightStem + factor[0] * (fatStem - lightStem)) + print factor, scale + f[name].interpolate(factor, f["A"], f["B"]) + f[name].scale((scale, 1)) + f[name].leftMargin = f["A"].leftMargin + f[name].rightMargin = f["A"].rightMargin +f.update() diff --git a/_downloads/interpolate_00.py b/_downloads/interpolate_00.py new file mode 100644 index 0000000..7a17849 --- /dev/null +++ b/_downloads/interpolate_00.py @@ -0,0 +1,4 @@ +from robofab.world import CurrentFont +f = CurrentFont() +a = f["a"] +print a.isCompatible(f["b"], False) diff --git a/_downloads/interpolate_01.py b/_downloads/interpolate_01.py new file mode 100644 index 0000000..ce8a029 --- /dev/null +++ b/_downloads/interpolate_01.py @@ -0,0 +1,4 @@ +from robofab.world import CurrentFont +f = CurrentFont() +a = f["a"] +print a.isCompatible(f["b"], True) diff --git a/_downloads/interpolate_02.py b/_downloads/interpolate_02.py new file mode 100644 index 0000000..07d3fab --- /dev/null +++ b/_downloads/interpolate_02.py @@ -0,0 +1,18 @@ +# robofab manual +# Interpolate howto +# Straight Interpolating examples + +from robofab.world import OpenFont +minFont = OpenFont(pathToMinFont) +maxFont = OpenFont(pathToMaxFont) +# or any other way you like to get two font objects + +inbetweenFont = OpenFont(pathToInbetweenFont) +# so now we have 3 font objects, right? + +inbetweenFont.interpolate(.5, minFont, maxFont) +# presto, inbetweenFont is now 50% of one and 50% of the other + +inbetweenFont.interpolate((.92, .12), minFont, maxFont) +# presto, inbetweenFont is now horizontally +# vertically interpolated in different ways. \ No newline at end of file diff --git a/_downloads/kerning_00.py b/_downloads/kerning_00.py new file mode 100644 index 0000000..f13ae7c --- /dev/null +++ b/_downloads/kerning_00.py @@ -0,0 +1,10 @@ +# showing where the data lives in the RoboFab objects. +from robofab.world import CurrentFont + +f = CurrentFont() + +# these are pairs +print f.kerning.keys() + +# get the value for this pair +print f.kerning[('MMK_L_baseserif', 'n')] \ No newline at end of file diff --git a/_downloads/lowLevel_00.py b/_downloads/lowLevel_00.py new file mode 100644 index 0000000..0ba2563 --- /dev/null +++ b/_downloads/lowLevel_00.py @@ -0,0 +1,6 @@ +from robofab.world import CurrentFont +f = CurrentFont() +# this is the high level RoboFab object +print f +# this is the low level FontLab object, not a part of RoboFab +print f.naked() diff --git a/_downloads/makeUFO_00.py b/_downloads/makeUFO_00.py new file mode 100644 index 0000000..fc2d170 --- /dev/null +++ b/_downloads/makeUFO_00.py @@ -0,0 +1,11 @@ +# robofab manual +# Makeufo howto +# Makeufo from a font binary examples + +from robofab.tools.toolsAll import fontToUFO +from robofab.interface.all.dialogs import GetFile, PutFile + +srcPath = GetFile('Select the source') +dstPath = PutFile('Save as...') + +fontToUFO(srcPath, dstPath) diff --git a/_downloads/nonelab_00.py b/_downloads/nonelab_00.py new file mode 100644 index 0000000..a7195bb --- /dev/null +++ b/_downloads/nonelab_00.py @@ -0,0 +1,25 @@ +# robothon06 +# demo of executing python in FontLab, MacOS only + +# this script runs in the Python IDE +# it will send some python code to FontLab +# FontLab will execute the python code: +# it will find the current glyph and send it to our other script. + +from robofab.tools.remote import runFontLabRemote, receiveGlyph +from robofab.world import RFont + +# this is what we want FontLab to do: +pythonCode = """ +from robofab.world import CurrentGlyph +from robofab.tools.remote import transmitGlyph +g = CurrentGlyph() +transmitGlyph(g) +""" + +# this the font where we'll store the glyph from FontLab +destFont = RFont() + +result = runFontLabRemote(pythonCode) +receiveGlyph(result, destFont) +print destFont.keys() diff --git a/_downloads/otFeatures_00.py b/_downloads/otFeatures_00.py new file mode 100644 index 0000000..45a3e4f --- /dev/null +++ b/_downloads/otFeatures_00.py @@ -0,0 +1,12 @@ +# Getting to feature data in a UFO. + +from robofab.world import OpenFont + +path = "A/path/to/font.ufo" + +f = OpenFont(path) + +print f.lib.keys() +print f.lib["com.robofab.features"] +print f.lib["com.robofab.features"]['liga'] +print f.lib["com.robofab.featureorder"] diff --git a/_downloads/otFeatures_01.py b/_downloads/otFeatures_01.py new file mode 100644 index 0000000..d836251 --- /dev/null +++ b/_downloads/otFeatures_01.py @@ -0,0 +1,8 @@ +# Getting to feature data in a FontLab +from robofab.world import CurrentFont + +f = CurrentFont() + +print f.naked().features + +# these are raw FontLab feature objects. \ No newline at end of file diff --git a/_downloads/pen_00.py b/_downloads/pen_00.py new file mode 100644 index 0000000..52144f4 --- /dev/null +++ b/_downloads/pen_00.py @@ -0,0 +1,11 @@ +# robofab manual +# Pen object +# usage examples + +from robofab.world import CurrentGlyph + +newGlyph = CurrentGlyph() + +pen = newGlyph.getPen() + +# do stuff with the pen to draw in this glyph diff --git a/_downloads/pens_00.py b/_downloads/pens_00.py new file mode 100644 index 0000000..324c0d0 --- /dev/null +++ b/_downloads/pens_00.py @@ -0,0 +1,25 @@ +# robofab manual +# Usepens howto +# usage examples + +from robofab.world import CurrentFont + +f = CurrentFont() + +newGlyph = f.newGlyph('demoDrawGlyph', clear=True) +newGlyph.width = 1000 + +# hey, what's this: +pen = newGlyph.getPen() +# ha! a sneaky way to get a pen object! + +pen.moveTo((100, 100)) +pen.lineTo((800, 100)) +pen.curveTo((1000, 300), (1000, 600), (800, 800)) +pen.lineTo((100, 800)) +pen.lineTo((100, 100)) +pen.closePath() + +newGlyph.update() + +f.update() \ No newline at end of file diff --git a/_downloads/pens_01.py b/_downloads/pens_01.py new file mode 100644 index 0000000..26e4dd5 --- /dev/null +++ b/_downloads/pens_01.py @@ -0,0 +1,13 @@ +# robofab manual +# Usepens howto +# attribute examples + +from robofab.world import OpenFont +from robofab.pens.digestPen import DigestPointPen + +f = OpenFont() + +myPen = DigestPointPen() +f['period'].drawPoints(myPen) + +print myPen.getDigest() diff --git a/_downloads/pens_02.py b/_downloads/pens_02.py new file mode 100644 index 0000000..cc1367f --- /dev/null +++ b/_downloads/pens_02.py @@ -0,0 +1,13 @@ +# robofab manual +# Usepens howto +# DigestPointStructurePen examples + +from robofab.world import OpenFont +from robofab.pens.digestPen import DigestPointStructurePen + +f = OpenFont() + +myPen = DigestPointStructurePen() +f['period'].drawPoints(myPen) + +print myPen.getDigest() diff --git a/_downloads/pens_03.py b/_downloads/pens_03.py new file mode 100644 index 0000000..ceba81e --- /dev/null +++ b/_downloads/pens_03.py @@ -0,0 +1,4 @@ +from robofab.world import CurrentGlyph +from robofab.pens.filterPen import flattenGlyph +d = 10 +flattenGlyph(CurrentGlyph(), d) diff --git a/_downloads/pens_04.py b/_downloads/pens_04.py new file mode 100644 index 0000000..2ec3dc0 --- /dev/null +++ b/_downloads/pens_04.py @@ -0,0 +1,4 @@ +from robofab.world import CurrentGlyph +from robofab.pens.filterPen import thresholdGlyph +d = 10 +thresholdGlyph(CurrentGlyph(), d) \ No newline at end of file diff --git a/_downloads/pens_05.py b/_downloads/pens_05.py new file mode 100644 index 0000000..769c522 --- /dev/null +++ b/_downloads/pens_05.py @@ -0,0 +1,5 @@ +from robofab.world import CurrentGlyph +from robofab.pens.filterPen import spikeGlyph +segmentLength = 20 +spikeLength = 100 +spikeGlyph(CurrentGlyph(), segmentLength, spikeLength) diff --git a/_downloads/pens_06.py b/_downloads/pens_06.py new file mode 100644 index 0000000..b4a54dd --- /dev/null +++ b/_downloads/pens_06.py @@ -0,0 +1,3 @@ +from robofab.world import CurrentGlyph +from robofab.pens.filterPen import halftoneGlyph +halftoneGlyph(CurrentGlyph()) diff --git a/_downloads/psHints_00.py b/_downloads/psHints_00.py new file mode 100644 index 0000000..33cd0f9 --- /dev/null +++ b/_downloads/psHints_00.py @@ -0,0 +1,11 @@ +# example of accessing the postscript blues +# data using the font.info attributes. + +from robofab.world import CurrentFont + +f = CurrentFont() + +print f.info.postscriptBlueValues +print f.info.postscriptOtherBlues +print f.info.postscriptFamilyBlues +print f.info.postscriptFamilyOtherBlues diff --git a/_downloads/psHints_01.py b/_downloads/psHints_01.py new file mode 100644 index 0000000..75603c7 --- /dev/null +++ b/_downloads/psHints_01.py @@ -0,0 +1,7 @@ +# example of accessing the hint data, +# using the font.psHints object. + +from robofab.world import CurrentFont + +f = CurrentFont() +print f.psHints.asDict() diff --git a/_downloads/psHints_02.py b/_downloads/psHints_02.py new file mode 100644 index 0000000..7ebda31 --- /dev/null +++ b/_downloads/psHints_02.py @@ -0,0 +1,18 @@ +# example of scaling the hint data. + +from robofab.world import CurrentFont + +f = CurrentFont() +print f.psHints.asDict() + +# a math operation returns a new, unbound object +ps2 = f.psHints * .5 + +# it needs to be rounded first +ps2.round() + +# now you can add the values to the FL object +f.psHints.update(ps2) + +# see those zones skip! +f.update() diff --git a/_downloads/psHints_03.py b/_downloads/psHints_03.py new file mode 100644 index 0000000..c494484 --- /dev/null +++ b/_downloads/psHints_03.py @@ -0,0 +1,96 @@ +#FLM: Get and set font level PostScript hint data. + +from robofab.world import CurrentFont +""" +This script shows the way to get to the font level postscript hint values. +These values were available from the fl layer, but not in RoboFab. +Now they're available in RoboFab in a slightly easier to use format. +The values also export to UFO and import from UFO. + +Check the FontLab FontInfo panel / Hinting Settings + +""" +f = CurrentFont() + +# the fontlevel postscript hint data is accessible through the psHints attribute + +print +print "This script shows the attributes of psHints:", f.psHints + +# now let's have a look at the values +# blueScale, blueShift, blueFuzz and forceBold are all single values. + +print "blueScale", f.psHints.blueScale +f.psHints.blueScale = .5 +print "blueScale changed", f.psHints.blueScale + +print "blueShift", f.psHints.blueShift +f.psHints.blueShift = 5 +print "blueShift changed", f.psHints.blueShift + +print "blueFuzz", f.psHints.blueFuzz +f.psHints.blueFuzz = 0 +print "blueFuzz changed", f.psHints.blueFuzz + +print "forceBold", f.psHints.forceBold +f.psHints.forceBold = 1 +print "forceBold changed", f.psHints.forceBold + +# the following values are represented as lists. +# Important Note: you can only set the whole list, not individual items. +# So get the list, make changes to it, then set the list +# Zones are represented as tuples of integers, so it's easier to +# see which values belong together. FL stores the values as +# a single list of numbers. + +# T1 spec says blueValues, FL says Primary Alignment Zones, under "Set Local Alignment Zones". +print "blueValues", f.psHints.blueValues +# remove the last zone +f.psHints.blueValues = f.psHints.blueValues[:-1] +print "blueValues changed", f.psHints.blueValues +# add a new zone +f.psHints.blueValues = f.psHints.blueValues + [(750, 770)] +print "blueValues changed", f.psHints.blueValues + +# T1 spec says otherBlues, FL says Secondary Alignment Zones, under "Set Local Alignment Zones". +print "otherBlues", f.psHints.otherBlues +# remove the last zone +f.psHints.otherBlues = f.psHints.otherBlues[:-1] +print "otherBlues changed", f.psHints.otherBlues +# add a new zone +f.psHints.otherBlues = f.psHints.otherBlues + [(750, 770)] +print "otherBlues changed", f.psHints.otherBlues + +# T1 spec says familyBlues, FL says Primary Alignment Zones, under "Set Family Alignment Zones". +print "familyBlues", f.psHints.familyBlues +# remove the last zone +f.psHints.familyBlues = f.psHints.familyBlues[:-1] +print "familyBlues changed", f.psHints.familyBlues +# add a new zone +f.psHints.familyBlues = f.psHints.familyBlues + [(750, 770)] +print "familyBlues changed", f.psHints.familyBlues + +# T1 spec says familyOtherBlues, FL says Seconday Alignment Zones, under "Set Family Alignment Zones". +print "familyOtherBlues", f.psHints.familyOtherBlues +# remove the last zone +f.psHints.familyOtherBlues = f.psHints.familyOtherBlues[:-1] +print "familyOtherBlues changed", f.psHints.familyOtherBlues +# add a new zone +f.psHints.familyOtherBlues = f.psHints.familyOtherBlues + [(750, 770)] +print "familyOtherBlues changed", f.psHints.familyOtherBlues + +# The horizontal stems are represented as a list of single values. +print "hStems", f.psHints.hStems +f.psHints.hStems = f.psHints.hStems[:-1] +print "hStems changed", f.psHints.hStems +# add a new stem +f.psHints.hStems = f.psHints.hStems + [100] +print "hStems changed", f.psHints.hStems + +# The vertical stems are represented as a list of single values. +print "vStems", f.psHints.vStems +f.psHints.vStems = f.psHints.vStems[:-1] +print "vStems changed", f.psHints.vStems +# add a new stem +f.psHints.vStems = f.psHints.vStems + [100] +print "vStems changed", f.psHints.vStems diff --git a/_downloads/scripting_00.py b/_downloads/scripting_00.py new file mode 100644 index 0000000..a04acf2 --- /dev/null +++ b/_downloads/scripting_00.py @@ -0,0 +1,4 @@ +from robofab.world import OpenFont +f = OpenFont() +# hey look! an open font dialog! +print f diff --git a/_downloads/scripting_01.py b/_downloads/scripting_01.py new file mode 100644 index 0000000..3fc82be --- /dev/null +++ b/_downloads/scripting_01.py @@ -0,0 +1,5 @@ +from robofab.world import OpenFont +path = "MyDrive/Folder1/Work/somefile" +f = OpenFont(path) +# hey look! it opens the file without asking.. +print f diff --git a/_downloads/scripting_02.py b/_downloads/scripting_02.py new file mode 100644 index 0000000..96e3aa8 --- /dev/null +++ b/_downloads/scripting_02.py @@ -0,0 +1,4 @@ +# in Fontlab: +from robofab.world import CurrentFont +f = CurrentFont() +print f diff --git a/_downloads/session1_00.py b/_downloads/session1_00.py new file mode 100644 index 0000000..9a312b0 --- /dev/null +++ b/_downloads/session1_00.py @@ -0,0 +1,2 @@ +from robofab.world import CurrentFont +print CurrentFont() \ No newline at end of file diff --git a/_downloads/session1_01.py b/_downloads/session1_01.py new file mode 100644 index 0000000..c3f6f13 --- /dev/null +++ b/_downloads/session1_01.py @@ -0,0 +1,3 @@ +# open a glyph in FL first! +from robofab.world import CurrentGlyph +print CurrentGlyph() diff --git a/_downloads/session1_02.py b/_downloads/session1_02.py new file mode 100644 index 0000000..28881f0 --- /dev/null +++ b/_downloads/session1_02.py @@ -0,0 +1,3 @@ +# open a couple of fonts in FL first! +from robofab.world import AllFonts +print AllFonts() diff --git a/_downloads/session1_03.py b/_downloads/session1_03.py new file mode 100644 index 0000000..cc23876 --- /dev/null +++ b/_downloads/session1_03.py @@ -0,0 +1,7 @@ +# open a couple of fonts in FL first! +from robofab.world import CurrentFont + +font = CurrentFont() +print font.path +print font.kerning +print font.info \ No newline at end of file diff --git a/_downloads/session1_04.py b/_downloads/session1_04.py new file mode 100644 index 0000000..565e797 --- /dev/null +++ b/_downloads/session1_04.py @@ -0,0 +1,16 @@ +# robothon06 +# getting data from the info object + +from robofab.world import CurrentFont + +font = CurrentFont() + +# naming attributes +print font.info.familyName +print font.info.styleName +print font.info.fullName + +# dimension attributes +print font.info.unitsPerEm +print font.info.ascender +print font.info.descender \ No newline at end of file diff --git a/_downloads/session1_05.py b/_downloads/session1_05.py new file mode 100644 index 0000000..f434669 --- /dev/null +++ b/_downloads/session1_05.py @@ -0,0 +1,22 @@ +# robothon06 +# setting data in the info object + +from robofab.world import CurrentFont + +font = CurrentFont() + +# naming attributes +font.info.familyName = "MyFamily" +print font.info.familyName +font.info.styleName = "Roman" +print font.info.styleName +font.info.fullName = font.info.familyName + '-' + font.info.styleName +print font.info.fullName + +# dimension attributes +font.info.ascender = 600 +print font.info.ascender +font.info.descender = -400 +print font.info.descender + +font.update() \ No newline at end of file diff --git a/_downloads/session1_06.py b/_downloads/session1_06.py new file mode 100644 index 0000000..166ef15 --- /dev/null +++ b/_downloads/session1_06.py @@ -0,0 +1,14 @@ +# robothon06 +# get a particular glyph + +from robofab.world import CurrentFont + +font = CurrentFont() + +font.info.familyName = "myFamilyName" +font.info.styleName = "myStyleName" +font.info.autoNaming() + +print font.info.fullName +print font.info.fontName +print font.info.fondName \ No newline at end of file diff --git a/_downloads/session1_07.py b/_downloads/session1_07.py new file mode 100644 index 0000000..66beae9 --- /dev/null +++ b/_downloads/session1_07.py @@ -0,0 +1,11 @@ +# robothon06 +# get a particular glyph + +from robofab.world import CurrentFont + +font = CurrentFont() + +print font['A'] +print font['Adieresis'] +print font['two'] +print font['afii12934'] \ No newline at end of file diff --git a/_downloads/session1_08.py b/_downloads/session1_08.py new file mode 100644 index 0000000..713d964 --- /dev/null +++ b/_downloads/session1_08.py @@ -0,0 +1,11 @@ +# robothon06 +# iteration through glyphs in a font + +from robofab.world import CurrentFont + +font = CurrentFont() + +print "font has %d glyphs" % len(font) + +for glyph in font: + print glyph \ No newline at end of file diff --git a/_downloads/session1_09.py b/_downloads/session1_09.py new file mode 100644 index 0000000..08f86d4 --- /dev/null +++ b/_downloads/session1_09.py @@ -0,0 +1,18 @@ +# iteration through alphabetically sorted glyphnames + +from robofab.world import CurrentFont + +font = CurrentFont() +print "font has %d glyphs" % len(font) + +# names is now a list of strings, the names of the glyphs +# not the glyphs themselves! +names = font.keys() + +# the list of names is sorted +names.sort() + +# now we iterate through the list of names +for glyphName in names: + # now we ask for the glyph with glyphName + print font[glyphName] diff --git a/_downloads/session2_00.py b/_downloads/session2_00.py new file mode 100644 index 0000000..400cff0 --- /dev/null +++ b/_downloads/session2_00.py @@ -0,0 +1,16 @@ +# robothon 2009 +# set basic attributes in a glyph + +from robofab.world import CurrentFont + +font = CurrentFont() +glyph = font['A'] + +print glyph.name +print glyph.width +print glyph.leftMargin +print glyph.rightMargin +print glyph.box +print glyph.unicode + +glyph.update() \ No newline at end of file diff --git a/_downloads/session2_01.py b/_downloads/session2_01.py new file mode 100644 index 0000000..1ca6856 --- /dev/null +++ b/_downloads/session2_01.py @@ -0,0 +1,21 @@ +# robothon06 +# set basic attributes in a glyph + +from robofab.world import CurrentFont + +font = CurrentFont() +glyph = font['A'] + +glyph.width = 200 +print glyph.width + +glyph.leftMargin = 50 +print glyph.leftMargin + +glyph.rightMargin = 50 +print glyph.rightMargin + +glyph.unicode = 666 +print glyph.unicode + +glyph.update() diff --git a/_downloads/session2_02.py b/_downloads/session2_02.py new file mode 100644 index 0000000..ff67613 --- /dev/null +++ b/_downloads/session2_02.py @@ -0,0 +1,18 @@ +# robothon06 +# use some methods to transform a glyph + +from robofab.world import CurrentFont + +font = CurrentFont() + +# ask a font for a glyph by name +glyph = font['A'] + +# now you have a glyph object +# make it do stuff by calling some of its methods +glyph.move((100, 75)) +glyph.scale((.5, 1.5)) +glyph.appendGlyph(font['B']) +glyph.removeOverlap() +glyph.correctDirection() +glyph.update() diff --git a/_downloads/session2_03.py b/_downloads/session2_03.py new file mode 100644 index 0000000..8a4cedf --- /dev/null +++ b/_downloads/session2_03.py @@ -0,0 +1,9 @@ +# robothon06 +# iterate through a glyph's contours + +from robofab.world import CurrentFont + +font = CurrentFont() + +glyph = font["A"] +print glyph.getParent() \ No newline at end of file diff --git a/_downloads/session2_04.py b/_downloads/session2_04.py new file mode 100644 index 0000000..6824924 --- /dev/null +++ b/_downloads/session2_04.py @@ -0,0 +1,10 @@ +# robothon06 +# iterate through a glyph's contours + +from robofab.world import CurrentFont + +font = CurrentFont() +glyph = font['A'] +print "glyph has %d contours" % len(glyph) +for contour in glyph.contours: + print contour \ No newline at end of file diff --git a/_downloads/session2_05.py b/_downloads/session2_05.py new file mode 100644 index 0000000..a1371d0 --- /dev/null +++ b/_downloads/session2_05.py @@ -0,0 +1,12 @@ +# robothon06 +# get a specific contour and view it +# through point, segment and bPoint structures + +from robofab.world import CurrentFont + +font = CurrentFont() +glyph = font['A'] +contour = glyph[0] +print contour.points +print countours.segments +print contour.bPoints diff --git a/_downloads/session2_06.py b/_downloads/session2_06.py new file mode 100644 index 0000000..a982a0b --- /dev/null +++ b/_downloads/session2_06.py @@ -0,0 +1,9 @@ +# robothon06 +# iterate through points + +from robofab.world import CurrentFont + +font = CurrentFont() +glyph = font['A'] +for p in glyph[0].points: + print p.x, p.y, p.type \ No newline at end of file diff --git a/_downloads/session2_07.py b/_downloads/session2_07.py new file mode 100644 index 0000000..2158f80 --- /dev/null +++ b/_downloads/session2_07.py @@ -0,0 +1,37 @@ +# robothon06 +# get a pen and draw something in the current glyph +# what will it draw? ha! run the script and find out! + +from robofab.world import CurrentGlyph + +g = CurrentGlyph() +myPen = g.getPen() + +# myPen is a pen object of a type meant for +# constructing paths in a glyph. +# So rather than use this pen with the glyph's +# own draw() method, we're going to tell it +# to do things ourselves. (Just like DrawBot!) +print myPen + +myPen.moveTo((344, 645)) +myPen.lineTo((647, 261)) +myPen.lineTo((662, -32)) +myPen.lineTo((648, -61)) +myPen.lineTo((619, -61)) +myPen.lineTo((352, 54)) +myPen.lineTo((72, 446)) +myPen.lineTo((117, 590)) +myPen.lineTo((228, 665)) +myPen.closePath() +myPen.moveTo((99, 451)) +myPen.lineTo((365, 74)) +myPen.curveTo((359, 122), (376, 178), (420, 206)) +myPen.curveTo((422, 203), (142, 579), (142, 579)) +myPen.closePath() +myPen.moveTo((631, -32)) +myPen.lineTo((629, 103)) +myPen.curveTo((556, 111), (524, 71), (508, 20)) +myPen.closePath() + +g.update() \ No newline at end of file diff --git a/_downloads/session2_08.py b/_downloads/session2_08.py new file mode 100644 index 0000000..ab5d93f --- /dev/null +++ b/_downloads/session2_08.py @@ -0,0 +1,15 @@ +# robothon06 +# get a pen and use it to print the coordinates +# to the output window. This is actually almost-python +# code which you can use it other scripts! + +from robofab.world import CurrentFont +from robofab.pens.pointPen import PrintingSegmentPen + +font = CurrentFont() +glyph = font['A'] + +# PrintingSegmentPen won't actually draw anything +# just print the coordinates to the output: +pen = PrintingSegmentPen() +glyph.draw(pen) diff --git a/_downloads/session2_09.py b/_downloads/session2_09.py new file mode 100644 index 0000000..8fa9d7f --- /dev/null +++ b/_downloads/session2_09.py @@ -0,0 +1,45 @@ +# robothon06 +# rasterise the shape in glyph "A" +# and draw boxes in a new glyph named "A.silly" + +from robofab.world import CurrentFont, CurrentGlyph + +sourceGlyph = "a" + +f = CurrentFont() +source = f[sourceGlyph] + +# find out how big the shape is from the glyph.box attribute +xMin, yMin, xMax, yMax = source.box + +# create a new glyph +dest = f.newGlyph(sourceGlyph+".silly") +dest.width = source.width + +# get a pen to draw in the new glyph +myPen = dest.getPen() + +# a function which draws a rectangle at a specified place +def drawRect(pen, x, y, size=50): + pen.moveTo((x-.5*size, y-.5*size)) + pen.lineTo((x+.5*size, y-.5*size)) + pen.lineTo((x+.5*size, y+.5*size)) + pen.lineTo((x-.5*size, y+.5*size)) + pen.closePath() + +# the size of the raster unit +resolution = 30 + +# draw from top to bottom +yValues = range(yMin, yMax, resolution) +yValues.reverse() + +# go for it! +for y in yValues: + for x in range(xMin, xMax, resolution): + # check the source glyph is white or black at x,y + if source.pointInside((x, y)): + drawRect(myPen, x, y, resolution-5) + # update for each line if you like the animation + # otherwise move the update() out of the loop + dest.update() diff --git a/_downloads/session2_10.py b/_downloads/session2_10.py new file mode 100644 index 0000000..8d031cc --- /dev/null +++ b/_downloads/session2_10.py @@ -0,0 +1,10 @@ +# use a point pen + +from robofab.world import CurrentFont +from robofab.pens.pointPen import PrintingPointPen + +font = CurrentFont() +glyph = font['A'] + +pen = PrintingPointPen() +glyph.drawPoints(pen) diff --git a/_downloads/session2_11.py b/_downloads/session2_11.py new file mode 100644 index 0000000..db5a168 --- /dev/null +++ b/_downloads/session2_11.py @@ -0,0 +1,15 @@ +# robothon06 +# Use FontLab pathfinder functionality to cut one glyph from another + +from robofab.world import CurrentFont + +f = CurrentFont() +base = f["A"] +cutter = f["B"] +dest = f["C"] + +dest.clear() +dest.appendGlyph(base) +dest.width = base.width +dest.naked().Bsubtract(cutter.naked()) +dest.update() diff --git a/_downloads/session3_00.py b/_downloads/session3_00.py new file mode 100644 index 0000000..415c28f --- /dev/null +++ b/_downloads/session3_00.py @@ -0,0 +1,12 @@ +# robothon06 +# work with kerning 1 +from robofab.world import CurrentFont +font = CurrentFont() +# now the kerning object is generated once +kerning = font.kerning +# and ready for your instructions. +print kerning +print len(kerning) +print kerning.keys() +# proceed to work with the myKerning object +# this happens in the following examples too. \ No newline at end of file diff --git a/_downloads/session3_01.py b/_downloads/session3_01.py new file mode 100644 index 0000000..066c6e8 --- /dev/null +++ b/_downloads/session3_01.py @@ -0,0 +1,23 @@ +# robothon06 +# work with kerning 2 + +from robofab.world import CurrentFont + +font = CurrentFont() +kerning = font.kerning + +# calculate the average offset +print kerning.getAverage() + +# count pairs with these glyphs +print kerning.occurrenceCount(["a", "b"]) + +# get the maximum values +print kerning.getExtremes() + +# count the pars +print "font has %d kerning pairs" % len(kerning) + +# this prints all the pairs +for (left, right), value in kerning.items(): + print (left, right), value \ No newline at end of file diff --git a/_downloads/session3_02.py b/_downloads/session3_02.py new file mode 100644 index 0000000..18091e1 --- /dev/null +++ b/_downloads/session3_02.py @@ -0,0 +1,12 @@ +# robothon06 +# work with kerning 3 +# print a specific set of pairs + +from robofab.world import CurrentFont + +font = CurrentFont() +kerning = font.kerning + +for left, right in kerning.keys(): + if kerning[(left, right)] < -100: + print left, right, kerning[(left, right)] \ No newline at end of file diff --git a/_downloads/session3_03.py b/_downloads/session3_03.py new file mode 100644 index 0000000..78859cd --- /dev/null +++ b/_downloads/session3_03.py @@ -0,0 +1,11 @@ +# robothon06 +# work with kerning 4 + +from robofab.world import CurrentFont + +font = CurrentFont() +kerning = font.kerning + +for left, right in kerning.keys(): + if left == "acircumflex": + print left, right, kerning[(left, right)] \ No newline at end of file diff --git a/_downloads/session3_04.py b/_downloads/session3_04.py new file mode 100644 index 0000000..91ce888 --- /dev/null +++ b/_downloads/session3_04.py @@ -0,0 +1,22 @@ +# robothon06 +# building a glyph from parts +# the hard way + +from robofab.world import CurrentFont + +f = CurrentFont() + +# make a new glyph +f.newGlyph("aacute") + +# add the component for the base glyph, a +f["aacute"].appendComponent("a") + +# add the component for the accent, acute +# note it has an offset +f["aacute"].appendComponent("acute", (200, 0)) + +# set the width too +f["aacute"].width = f["a"].width + +f.update() \ No newline at end of file diff --git a/_downloads/session3_05.py b/_downloads/session3_05.py new file mode 100644 index 0000000..3736e17 --- /dev/null +++ b/_downloads/session3_05.py @@ -0,0 +1,28 @@ +# robothon06 +# Compile a new glyph from a list of accents and required anchors +# Demo of multiple accents chaining together, or "stacking". +# For this example you need to set up a couple of things +# in your test font: +# - base glyph "a", with anchor "top" and anchor "bottom" +# - glyph "dieresis" with anchor "_top" and anchor "top" +# - glyph "acture" with anchor "_top" +# - glyph "cedilla" with anchor "_bottom" + +from robofab.world import CurrentFont + +font = CurrentFont() + +# this is a list of tuples +# each tuple has the name of the accent as first element +# and the name of the anchor which to use as the second element + +accentList = [("dieresis", "top"), + ("acute", "top"), + ("cedilla", "bottom")] + +# The accents are compiled in this order, so first +# "dieresis" connects to "a" using "top" anchor +# "acute" connects to dieresis, using the next "top" anchor + +font.compileGlyph("myCompiledGlyph", "a", accentList) +font.update() diff --git a/_downloads/session6_00.py b/_downloads/session6_00.py new file mode 100644 index 0000000..02265e4 --- /dev/null +++ b/_downloads/session6_00.py @@ -0,0 +1,10 @@ +# robothon06 +# set font info in all fonts + +from robofab.world import AllFonts + +for font in AllFonts(): + font.info.familyName = "MyFamily" + font.info.ascender = 700 + font.info.descender = -300 + font.update() diff --git a/_downloads/session6_01.py b/_downloads/session6_01.py new file mode 100644 index 0000000..5f21ad5 --- /dev/null +++ b/_downloads/session6_01.py @@ -0,0 +1,25 @@ +# robothon 2006 +# get info attributes for all fonts +# and dump them to a text file + +from robofab.world import AllFonts +from robofab.interface.all.dialogs import PutFile + +text = [] + +for font in AllFonts(): + text.append(str(font.path)) + text.append(str(font.info.familyName)) + text.append(str(font.info.styleName)) + text.append(str(font.info.fullName)) + text.append(str(font.info.unitsPerEm)) + text.append(str(font.info.ascender)) + text.append(str(font.info.descender)) + text.append('') + +text = '\n'.join(text) +path = PutFile('Save file as:') +if path: + file = open(path, 'w') + file.write(text) + file.close() \ No newline at end of file diff --git a/_downloads/session6_02.py b/_downloads/session6_02.py new file mode 100644 index 0000000..c96e919 --- /dev/null +++ b/_downloads/session6_02.py @@ -0,0 +1,13 @@ +# robothon 2006 +# batch save as + +import os +from robofab.world import AllFonts +from robofab.interface.all.dialogs import GetFolder + +path = GetFolder() +if path: + for font in AllFonts(): + fileName = os.path.basename(font.path) + newPath = os.path.join(path, fileName) + font.save(newPath) \ No newline at end of file diff --git a/_downloads/session6_03.py b/_downloads/session6_03.py new file mode 100644 index 0000000..cec7f99 --- /dev/null +++ b/_downloads/session6_03.py @@ -0,0 +1,24 @@ +# robothon 2006 +# batch interpolate + +import os +from robofab.world import SelectFont, NewFont + +# ask for two masters to interpolate: +font1 = SelectFont("Select font 1") +font2 = SelectFont("Select font 2") +# these are the interpolation factors: +values = [.3, .6] + +for value in values: + # make a new font + destination = NewFont() + # do the interpolation + destination.interpolate(value, font1, font2, doProgress=True) + destination.update() + # make a new path + filename for the new font to be saved at: + dir = os.path.dirname(font1.path) + fileName = "Demo_%d.vfb" % (1000 * value) + # save at this path and close the font + destination.save(os.path.join(dir, fileName)) + destination.close() \ No newline at end of file diff --git a/_downloads/session6_04.py b/_downloads/session6_04.py new file mode 100644 index 0000000..2363243 --- /dev/null +++ b/_downloads/session6_04.py @@ -0,0 +1,40 @@ +# robothon06 +# ask for a folder +# find (nested) fontlab files in the folder +# open the fonts +# Demonstrates: recursive function,, dialog, os module + +import os.path +from robofab.interface.all.dialogs import GetFolder +from robofab.world import OpenFont + +# this function looks for fontlab files in a folder +def walk(someFolder, extension): + extension = extension.lower() + files = [] + # the os module has tools to deal with + # the operating system. This returns a list of names + # of stuff in the folder you feed it: + names = os.listdir(someFolder) + for n in names: + p = os.path.join(someFolder, n) + # if this new thing is a folder itself, + # call this function again, but now with the + # new path to check that as well. This is + # called recursion. + if os.path.isdir(p): + # add the results of the other folder + # to the list + files += walk(p, extension) + continue + # is it a file with the extension we want? + # add it then! + if n.lower().find(extension) <> -1: + files.append(p) + return files + +yourFolder = GetFolder("Search a folder:") +if yourFolder is not None: + fontPaths = walk(yourFolder, ".vfb") + for path in fontPaths: + OpenFont(path) diff --git a/_downloads/session6_05.py b/_downloads/session6_05.py new file mode 100644 index 0000000..781d256 --- /dev/null +++ b/_downloads/session6_05.py @@ -0,0 +1,14 @@ +# rename the selected glyphs +# in the current font to .sc + +from robofab.world import CurrentFont +f = CurrentFont() + +for g in f: + if g.selected == 0: + continue + newName = g.name+".sc" + print "moving", g.name, "to", newName + f.insertGlyph(g, name=newName) + f.removeGlyph(g.name) + f.update() diff --git a/_downloads/session6_06.py b/_downloads/session6_06.py new file mode 100644 index 0000000..c6cbf48 --- /dev/null +++ b/_downloads/session6_06.py @@ -0,0 +1,7 @@ +# robothon 2006 +# batch generate + +from robofab.world import AllFonts + +for font in AllFonts(): + font.generate('otfcff') \ No newline at end of file diff --git a/_downloads/session6_07.py b/_downloads/session6_07.py new file mode 100644 index 0000000..9c2b0c1 --- /dev/null +++ b/_downloads/session6_07.py @@ -0,0 +1,46 @@ +# robothon 2006 +# a more robust batch generator that only has one font open at the time. + +from robofab.interface.all.dialogs import GetFolder +from robofab.world import RFont, OpenFont +import os + +def collectSources(root): + files = [] + ext = ['.vfb'] + names = os.listdir(root) + for n in names: + if os.path.splitext(n)[1] in ext: + files.append(os.path.join(root, n)) + return files + +# A little function for making folders. we'll need it later. +def makeFolder(path): + # if the path doesn't exist, make it! + if not os.path.exists(path): + os.makedirs(path) + +def makeDestination(root): + macPath = os.path.join(root, 'FabFonts', 'ForMac') + makeFolder(macPath) + return macPath + +def generateOne(f, dstDir): + print "generating %s"%f.info.fullName + f.generate('otfcff', dstDir) + +f = GetFolder() + +if f is not None: + paths = collectSources(f) + dstDir = makeDestination(f) + for f in paths: + font = None + print f + try: + font = OpenFont(f) + generateOne(font, dstDir) + finally: + if font is not None: + font.close(False) + print 'done' diff --git a/_downloads/session6_08.py b/_downloads/session6_08.py new file mode 100644 index 0000000..81ace46 --- /dev/null +++ b/_downloads/session6_08.py @@ -0,0 +1,40 @@ +# robothon 2006 +# merge two fonts + +from robofab.world import SelectFont, NewFont +from robofab.pens.digestPen import DigestPointPen +from sets import Set + +font1 = SelectFont("Select base font") +font2 = SelectFont("Select alternate font") + +font1Names = Set(font1.keys()) +font2Names = Set(font2.keys()) + +commonNames = font1Names & font2Names +uncommonNames = font2Names - font1Names + +for glyphName in commonNames: + glyph1 = font1[glyphName] + pointPen = DigestPointPen() + glyph1.drawPoints(pointPen) + digest1 = pointPen.getDigest() + + glyph2 = font2[glyphName] + pointPen = DigestPointPen() + glyph2.drawPoints(pointPen) + digest2 = pointPen.getDigest() + + if digest1 != digest2: + print '> alt >', glyphName + glyph3 = font1.insertGlyph(glyph2, name=glyphName+'.alt') + glyph3.mark = 1 + glyph3.update() + +for glyphName in uncommonNames: + print '>', glyphName + glyph = font1.insertGlyph(font2[glyphName]) + glyph.mark = 60 + glyph.update() + +font1.update() \ No newline at end of file diff --git a/_downloads/session6_09.py b/_downloads/session6_09.py new file mode 100644 index 0000000..040c97b --- /dev/null +++ b/_downloads/session6_09.py @@ -0,0 +1,9 @@ +# show the objects from the fontlab layer + +from robofab.world import CurrentFont + +f = CurrentFont() +print f.naked() + +g = f["A"] +print g.naked() diff --git a/_downloads/session6_10.py b/_downloads/session6_10.py new file mode 100644 index 0000000..5c9ba1e --- /dev/null +++ b/_downloads/session6_10.py @@ -0,0 +1,3 @@ +# show vhints for current glyph +g = CurrentGlyph() +g.naked().vhints diff --git a/_downloads/session6_11.py b/_downloads/session6_11.py new file mode 100644 index 0000000..13d4c0f --- /dev/null +++ b/_downloads/session6_11.py @@ -0,0 +1,11 @@ +# robothon06 +# show OpenType naming records +# in the fontlab API + +from robofab.world import CurrentFont + +f = CurrentFont() +fn = f.naked() + +for r in fn.fontnames: + print r.nid, r.pid, r.eid, r.lid, r.name diff --git a/_downloads/session6_12.py b/_downloads/session6_12.py new file mode 100644 index 0000000..1e72392 --- /dev/null +++ b/_downloads/session6_12.py @@ -0,0 +1,15 @@ +# robothon06 +# show encoding + +from robofab.world import CurrentFont + +f = CurrentFont() +fn = f.naked() + +# object containing encoding records. +# you can iterate through it by using an index. +print fn.encoding + +for i in range(len(fn.encoding)): + er = fn.encoding[i] + print er, er.name, er.unicode diff --git a/_downloads/transformations_00.py b/_downloads/transformations_00.py new file mode 100644 index 0000000..ef9d133 --- /dev/null +++ b/_downloads/transformations_00.py @@ -0,0 +1,17 @@ +# robofab manual +# Usetransformations howto +# usage examples + +from fontTools.misc.transform import Identity +from robofab.world import CurrentFont + +m = Identity +print m + +m = m.rotate(math.radians(20)) +print m + +f = CurrentFont() +for c in f: + c.transform(m) + c.update() \ No newline at end of file diff --git a/_downloads/understandingContours_00.py b/_downloads/understandingContours_00.py new file mode 100644 index 0000000..e03eeff --- /dev/null +++ b/_downloads/understandingContours_00.py @@ -0,0 +1,4 @@ +# take a glyph (one with outlines obviously) +g = CurrentGlyph() +# get to contours by index: +print g[0] \ No newline at end of file diff --git a/_downloads/understandingContours_02.py b/_downloads/understandingContours_02.py new file mode 100644 index 0000000..b717bde --- /dev/null +++ b/_downloads/understandingContours_02.py @@ -0,0 +1,5 @@ +# get straight to the points in a contour +# through the points attribute +g = CurrentGlyph() +for aPt in g[0].points: + print aPt diff --git a/_downloads/understandingContours_03.py b/_downloads/understandingContours_03.py new file mode 100644 index 0000000..d5f5f6f --- /dev/null +++ b/_downloads/understandingContours_03.py @@ -0,0 +1,7 @@ +# bpoints +c = CurrentGlyph() +for aPt in c[0].bPoints: + print aPt.anchor + print aPt.bcpIn + print aPt.bcpOut + print aPt.type diff --git a/_images/ObjectModel.svg b/_images/ObjectModel.svg new file mode 100644 index 0000000..2154bdc --- /dev/null +++ b/_images/ObjectModel.svg @@ -0,0 +1,577 @@ + + + + + Robofab Object Model + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/_images/RAnchor.gif b/_images/RAnchor.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0860fcda56c6f34535b5527e62765d9aeefe6a8 GIT binary patch literal 2073 zcmdUs311U;0zm&WxgZ1y;V?jyaF}q3L15%?WrA|4AX2~}P=g>pH-JWNkFpaGNoS3&n99MNxgM z^;8;Xt~yOFm+KR3W+kz@Eo5(R@2?ONolZaKOn7s<&6EfXSLzG~gI=$n$?%;&lk+Ur zqH-2{|H!bq$4kZ0{YR}u=t5bV8+90w}C=9WN?To?4g+G>N^+Q8L&yNPl zWU|?^?Vs7fVzHRbW~1MqqM##QCjlfEWYoGMVlu>?a0bWT+goHea%7NQ6#*|u#+1Fl<0`h%< zwFj9BX(BbjiB#3llFO!9fIk6lbP#eDHKYyzGeK+&Bq(uK!8EePF zORN2-UyS^aWA*7DEhY`-o~4B!2%zG*{>Pu}`>}U~tc@`?mn&Bge zW&8*r3W$#=E*(=i4w%@dr#`64uRt|4&beM~OaOLZckUGB3_T)t z4#vBZa|5<I?lQvgwj%2lnrAg(4CMtx2k%Bb=55RQNtXgIP#SPLD;w1HNi?U&}BhFDhe7_vAPY zP&w<*<_>T-mvt7)LbKlu=UVzV}$u zxAN^7KuxWa78^184ayEiW@o{h@3|8Yl@X2wUvNUlBoCdu4E3n-@JFK-ul)<7%LfP% z!ppE_63EiLTsS5%qAGTvCL0$#GH!7`$No!Fi!y@1*%(xo9v75YO$@ueH6(xai1iU4 zDqmVDL}=Yud&6{|Pu*4|{)Me^sMv!Gu<4i)TErdV79dE5HZnC-U)0;BcITRS>@_9!mceWU5L7;31li64vI*m%QED( zjIzyZ0yTD*P|ddM)+bA&s6`CzfXli=0<{w|u{(Zmmw3G1m|MVw`;ZPeOQmxO_Xx}Npiekplx zxwK)(-^5Mg2<`OS=$kv}pq+WTyaPv-3i z8E=N2y(Re{``>HykETS8Dx;#6JwcjOC}X*ogVsIBZS$sM-0i2{}jl zasYa>GjO;8YjTxb^hWg;;+XoiPjq3_fI*Au$GPoG>MCjxAjDtOQs}}82RB1qTp>pI zPlG<{=n<(AZ?mEt@P`G5?&p++k;wVV-iVr!?RHZ0j&dWu&+bWy5XWta#wW-{@&|jw z@2oZ%+yqYMFml(|ksRKi{O98#*1WJaC+m1@)!;*|8*vriRK-Ds1d87;kbmKclwGw_ oR;+MUpH-JWNkFpaGNoS3&n99MNxgM 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≀Ed!@i zg%E576ybc=v-r_0NzYy+xVy{gEHzs)z7;@dq-8d&^mkkZbj7G4)~C@dy9!QDL!t8$ zz&aiOODSh>`Db8=@PFrgRKG~XF`~{?mYP9$0%l9RlKXi(PgcnFPs#BNL!%#b)Hd7xl&H z*II`?bx2Y~MnrDDV3l;QwN1jk^;@GT(RSjoWd|19lReVF&ls2zcD!77RL?`T>DGtg z3Q~g~uWcUq-ZxkKaGyg+*)lqgwAB}(J+}?__qm@$qxR%54Mm#!Fl7&_YS)Ot&rb6; zDNeA(@r9g;sU_B|Ga$<+4X6TL5e38(9SnL5d literal 0 HcmV?d00001 diff --git a/_images/RFont.gif b/_images/RFont.gif new file mode 100644 index 0000000000000000000000000000000000000000..4ecd203149e860ab5a89dd53636512e1e4801a78 GIT binary patch literal 2973 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 literal 0 HcmV?d00001 diff --git a/_images/RGlyph1.gif b/_images/RGlyph1.gif new file mode 100644 index 0000000000000000000000000000000000000000..cfa43a64eef7d44e0faf50a02a72aaf738818ab1 GIT binary patch literal 3186 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 literal 0 HcmV?d00001 diff --git a/_images/RInfo.gif b/_images/RInfo.gif new file mode 100644 index 0000000000000000000000000000000000000000..374ab7809822ea5db8d6636a4a487bb8af7198e2 GIT binary patch literal 1929 zcmdUsheK0$0>^*vy%3U+gb)NG0)`FB2rD87_=uGuqj6NJwHO5j17a9juoPbcHmpDx zLPf+NMIxg{4rF-3V_CGo0a_WN7lvqo^Md0JDLu~q8Ta`MKA-P5Ajscy=kY|q0}CiX zRfPZm#UzfRXn043s85+S+`O@|;onqzwzmPpu=1z(_qSeQhX-CCAJAwt3))5=2s&g=W}Ia34vWY2u913{r!yR^tRnZNJ^V=^5S;(HKH_iJqq=SgyK4pq2XPz^ zX(_dfKcY}5T4#Q(pB_HkUP(3I!e+BK?QnE+b1NR}CK)nCB2i>#jY_3@rdbSbE^{w9 zr&g<_LmhItoX_X?E=+$r@K=-2T@I;{uRg52TU-64`pN(Q7xRw<2mll~{F(6QCqR1x zLnRrRm%f)~W#{DP$?^;2g+;|BmrKijxKe(#;#%c(Mb(XL3rh;3yj54vp_taIkVZ~r6)(Z9qPindwTo&yOoWumb$H_t~-0T8PjM6Pd9_fsb|yAr#3$|*y3%xt$!!Q zhC7t6Ys$c#jjSi8tVolDwclU-@!x+K>~(Jwgs}(*P5o7F^TS4$Qa=EWodA_!xhywf zo&e{O(l&TP{Q%JfMQhM7M>GL4eCRr^{wluW=FnA-$P;;rq-ybXqUSW#4-@Ya`GkWE ztm#VjF{5U4McZQpl3Ucgc~++z4e1aqVm7JNwNlu>{kYxAtWjp>jg3lTR=G?Z4l%ud z9C}pdjKJ(T5)Pixa&lT7X>B?gPvT+yZ3;j>!{V+l$`gx8Dam@_ zZ86Z&%keTjOf4$weHCY&-eM>FEg2Y2GQy7n`0mOa@TFEZG!iZWM{WyA(^DgA`nE8( zb#UgyN}NZ!{lJgv!!$tZa~kNp?{kdtqQzs?dTtC!*)pOV{jbi8fvfQHuTLpuRL#}& ziI27HW6$@1q8O-QcQzH`%e&7lIVz6_j(;f+C02iNLVy6gZ038rfA8jn5TXvqc}02r zs^I!m`K;_k8XF}{9@XeX7KM~;g^gCEb27ty#F>qh!huyDSF@5bUox4=#-s-8u9($` zoP-Os@KT&?8^Y-&xMa=aWcq7)kL)uifR;jWp}&Re#!%>a#v+nhXXX`mF3G+GKd)1$?-enZi2?Z+S7a`0E0%LxPqv@1&Enm zb%9DI1%*9bRhGcF(>SR1+^Ddg>$0plwL{sV3Z?!cR8~u!>Dyy{ADBsd8Z*o=m~wJW zV?%K>QS_2s`Z)F!UrmP~${YadSy^7znZ}5|~ zBbANG_L6_sv{*|nOjEUE-JoF$M9!;oyBC{uaXUpbnFQgaY;p3(M~ex*Q4M$QxmbO@ z?e^!p{u%Mj@dZObC{9MduHL_;wRv0{^G?FK&W`VB+N(>Iw{_H?X0i?59|4@cvqy7P z?IO@&K6n2PelFTAgFg8hOTBoazn)8Y?=>3^e4>zrSbHp2g3#L-$b-gOHN3PVMCC<^ zKeX03_-2m{1Xz4py;WDrX>09+H(9m&x+PAtVrFQ?x+KG%oJTIj`R3D)V`KE*vZ$T* z8`g=JfAT!}{GJs3hRNpd{wg*&JeyVk32J1&oejYDn6WWv9Rg$43O}e!?r?Fy4;%g= zLo8v0=_lIzar-2`gd_f3!_zd)1>&`leembGbw%$T?3m0=Y#XBB=xV7&R|skeKCq~7 z16fRFasV)y2&S2kpsz%d^d$1|e_|$di4CV9vo>11@-BDl`JOY7T)^#!1mkkiHkU8) zfV*OdP84W`Eoaiye&Tmgksf-h`C8G%{cxL&d&siFjvgRhkD5bVvcZv?nc%xj9Lea; z{i3Z9GV3c8nJxFt7#irk418eeFA3eMr62f^g(GbKtdy(9Yo16KOcTX9n@8V4=$rW> zEjH!wq4vu-R%6RlJk(~57w}*{%QU9yfEuD2l&}+~G?5S>Z_3R(>0laU4Y_|TFcvkj zY=h<jJ$VU_m(`hf;DVUWurr6pC`Pe=h%@+ni zzu>QJLR2}j3r|>%s1%N3_!s8z2(F4ta7tm0%#5(P8Sf^YUmUAkdtZyv>iE)}EEIsh F{0|j8=57E0 literal 0 HcmV?d00001 diff --git a/_images/RKerning.gif b/_images/RKerning.gif new file mode 100644 index 0000000000000000000000000000000000000000..f8b936f8f48ff13c90f0387145e3b425948faea9 GIT binary patch literal 1955 zcmV;U2VD3^Nk%w1VR8UM0M$JJLb%ib005!e>T${5S-{zG$=|@hz=_i2pxfzX#oYh@ z|Ih98AzW%ryw*p$)wtyDQ@+@b)a5aXpPSg|5H2-{(&Ws{%$3&X5D*Z3&f)X={M+&N z3?e5$KtO%X;jG{6l-K5i(Bq(>pu_0#cgx`L@bEpX#wBNWU&7iTARusXa4mk3=l1z) z$K4o3PdTBv;NajhGcyPm8UzasfPjFou&_{2P!u^rU|?V=bA%jFTs4)fkdTo7|Nj60 z00000A^8LW002DzEC2ui0CE6A000L6z@BhOEEc16bvU4F952mtgWuEuR9Vajei|9HD;ek28wy55~~daEd?P31s(^> z%O1$c1OyJS)UUHHn0**3aJw+R6f3MKBo_kb=;`X~2Pn_)1<~@=tg{S_GkP5cpEaX5 z!BjO!VD8+7W76nBcou@0!vh7^p^I>UL;(~8AiOe>CAuIyA3nVnsTS?DB zv}YuisY4lU+Nu{W^k5JXrpCzsRVXH$E1;64(W9;g9yoa*1c93!^Qib@VH8PK9?nH5 zinOa&04@`Rn3#Z7jyxSaZK)dIssob(3VfYQR}}#dLN63O8z6>SEG0&9Q1w>8gr{{A ze|3;mKv`81^4ZX0BfyMQ4NOkps<`vf0_PqBSdoY46$5$172fQ*b=L&vP^|KZq1%)a zigbY0%-OZ?YM>`HQ1v1Y4J#@F$k=VT_wVPgmPS~GDMppR0fLQX4ZS-x2j=7gI3bk^ zjQ|wDoU6bAT)Q?%a+3dK;xHhR-nNMNWmtT9wb7M$10!=$O-})3`b#7AZ#emk^m%7 z)&K~60005~+0|c*6(C?_0*tOQKm`kAFhYw)kq{RE2}bd!Dy9m$3IYodFv0?^B%nbB z1h9Yr0SmCOzy}{Ju;c?8fbc;EEZ_;L1}vyDzy>2c073-{7})@{MJmALN=p$iUjQjc zu_^%FzNtY18z=z(BP$Qk3cv@=0+0cV3%m#bwJmPBO0cUC8)v=uDuCFGT?yp?c>zoY z1q|bst0k=jY)~jG3wQ~DzVbGUzzD;w_$rsG@T&@}F4BrI02<6`lmkElkW&CWM1fiW zt2pe+0vf0?FP^Kgu)(M4I=ewD1H^mr(5kfis>;7!Y_x`Co_eOt4GZ9^Dota3?kY20 zikQc&WZ>?_V^_Sd#Q>NMf&#-epe|D8Kwv_uP|UoFP*X(00_W~X_v$qG;l481c0D{1_%t4A%_HH zSk?m{Ado@xM!|Lf0CVR7lDGjdpo;jeAmG0H0}y~f1^t09>H^kY+Ud0Z=|4aQl!~AC z`gf^!Dd2z#(7>4J(Ez*wKnL`p0v>K)7s%1+D;3CqqwK`9YK-MTJJ17~ppcvy2;>|W z?8*lcxC&9x0|g;66I!Yuk^rm;04B*>3STh-`n7Ofuy_k=AeaZ+M8N{7VU=Tc7(SIX z-~n-Zg##Ldpz>JZCq5FuftaYI2RtBJQGCT%#`l73q~I@9pppsIGXXBP#sNz?fCFBT zj~rqDp@!nXVT#g0HD!gG%pB& z1T^LX9=N7Q_K=n_;6M*LxFH1a0yz?(Aeg=xMgoj+0Jv1M1)O=o31rZR;*JnRWC90p1~O34n;kG9o1WyQ7!ax)2BcyYgF;64VbJFwHJ{V1QBV;Rbnp1q9?l40sr|00P2iHB7Jq9e{KXI1uS4O7KoT z$UvcAVyaXBkOv!_Z>LDG0G0T_ffJm_GZK)%3L@cxn{t&CXas8#ET95r_F)E=V89A) z2!I!)^{+X2L?fQc)nww}t8%T|SPRS8#{MA%HsFC&6Z-@hRMoMV^@An^u}#Wmp$urS pgHJO{pAK{Y2Rtx9Ts^xBI-G$9u*HQLCd=B|+V-}%jYALs06W^oM+N`@ literal 0 HcmV?d00001 diff --git a/_images/RKerning1.gif b/_images/RKerning1.gif new file mode 100644 index 0000000000000000000000000000000000000000..f8b936f8f48ff13c90f0387145e3b425948faea9 GIT binary patch literal 1955 zcmV;U2VD3^Nk%w1VR8UM0M$JJLb%ib005!e>T${5S-{zG$=|@hz=_i2pxfzX#oYh@ z|Ih98AzW%ryw*p$)wtyDQ@+@b)a5aXpPSg|5H2-{(&Ws{%$3&X5D*Z3&f)X={M+&N z3?e5$KtO%X;jG{6l-K5i(Bq(>pu_0#cgx`L@bEpX#wBNWU&7iTARusXa4mk3=l1z) z$K4o3PdTBv;NajhGcyPm8UzasfPjFou&_{2P!u^rU|?V=bA%jFTs4)fkdTo7|Nj60 z00000A^8LW002DzEC2ui0CE6A000L6z@BhOEEc16bvU4F952mtgWuEuR9Vajei|9HD;ek28wy55~~daEd?P31s(^> z%O1$c1OyJS)UUHHn0**3aJw+R6f3MKBo_kb=;`X~2Pn_)1<~@=tg{S_GkP5cpEaX5 z!BjO!VD8+7W76nBcou@0!vh7^p^I>UL;(~8AiOe>CAuIyA3nVnsTS?DB zv}YuisY4lU+Nu{W^k5JXrpCzsRVXH$E1;64(W9;g9yoa*1c93!^Qib@VH8PK9?nH5 zinOa&04@`Rn3#Z7jyxSaZK)dIssob(3VfYQR}}#dLN63O8z6>SEG0&9Q1w>8gr{{A ze|3;mKv`81^4ZX0BfyMQ4NOkps<`vf0_PqBSdoY46$5$172fQ*b=L&vP^|KZq1%)a zigbY0%-OZ?YM>`HQ1v1Y4J#@F$k=VT_wVPgmPS~GDMppR0fLQX4ZS-x2j=7gI3bk^ zjQ|wDoU6bAT)Q?%a+3dK;xHhR-nNMNWmtT9wb7M$10!=$O-})3`b#7AZ#emk^m%7 z)&K~60005~+0|c*6(C?_0*tOQKm`kAFhYw)kq{RE2}bd!Dy9m$3IYodFv0?^B%nbB z1h9Yr0SmCOzy}{Ju;c?8fbc;EEZ_;L1}vyDzy>2c073-{7})@{MJmALN=p$iUjQjc zu_^%FzNtY18z=z(BP$Qk3cv@=0+0cV3%m#bwJmPBO0cUC8)v=uDuCFGT?yp?c>zoY z1q|bst0k=jY)~jG3wQ~DzVbGUzzD;w_$rsG@T&@}F4BrI02<6`lmkElkW&CWM1fiW zt2pe+0vf0?FP^Kgu)(M4I=ewD1H^mr(5kfis>;7!Y_x`Co_eOt4GZ9^Dota3?kY20 zikQc&WZ>?_V^_Sd#Q>NMf&#-epe|D8Kwv_uP|UoFP*X(00_W~X_v$qG;l481c0D{1_%t4A%_HH zSk?m{Ado@xM!|Lf0CVR7lDGjdpo;jeAmG0H0}y~f1^t09>H^kY+Ud0Z=|4aQl!~AC z`gf^!Dd2z#(7>4J(Ez*wKnL`p0v>K)7s%1+D;3CqqwK`9YK-MTJJ17~ppcvy2;>|W z?8*lcxC&9x0|g;66I!Yuk^rm;04B*>3STh-`n7Ofuy_k=AeaZ+M8N{7VU=Tc7(SIX z-~n-Zg##Ldpz>JZCq5FuftaYI2RtBJQGCT%#`l73q~I@9pppsIGXXBP#sNz?fCFBT zj~rqDp@!nXVT#g0HD!gG%pB& z1T^LX9=N7Q_K=n_;6M*LxFH1a0yz?(Aeg=xMgoj+0Jv1M1)O=o31rZR;*JnRWC90p1~O34n;kG9o1WyQ7!ax)2BcyYgF;64VbJFwHJ{V1QBV;Rbnp1q9?l40sr|00P2iHB7Jq9e{KXI1uS4O7KoT z$UvcAVyaXBkOv!_Z>LDG0G0T_ffJm_GZK)%3L@cxn{t&CXas8#ET95r_F)E=V89A) z2!I!)^{+X2L?fQc)nww}t8%T|SPRS8#{MA%HsFC&6Z-@hRMoMV^@An^u}#Wmp$urS pgHJO{pAK{Y2Rtx9Ts^xBI-G$9u*HQLCd=B|+V-}%jYALs06W^oM+N`@ literal 0 HcmV?d00001 diff --git a/_images/RPoint.gif b/_images/RPoint.gif new file mode 100644 index 0000000000000000000000000000000000000000..50d2319d1874548458d248edab3d6c518ffb9295 GIT binary patch literal 1968 zcmdUsi$7HP0>FQB=7BjgV=$iE<6w|S-fz+vw6q?R=GHB$p>CqB&dQ^Fsy#D9UN=U_ zBW1`dWQSF$|lq396=BOb14+EBd##wwBXMTu6+mJ%{Jfqzh`>-d{_8tM8>md{$Og za2)4wI3Jq3m`vu((X(^{F%vfak?Hi#H+&)S+ezop|5PW5w|d`l}aUwqMPH> zpI*K0>+4gf+nE!o2PxVSDtbjUGaiq(csct|$v^%7e=+<-A^^YvR(~b@^#rJFVH}Y- zIpun4T6#w2KW}7ZOLA`J=H=fiC@d-q9&%Atcj!*=!C~ohVyc>9E&p;;ggD<)y~k5lhV?_tiGEwGTgV7EaZk#V1f~k(Eg2|!x!i}8 zId3#JX8SPaZ~2U43|GU4_)vn|B^2g~uqTIoiL-;UrR0CnPi&R-=3BOi`(Wx9wqGL` z{n}|KiK-v+5+1Z^Cy|@eJmifh6Ev*Zr+b9n!SN24#vt$3U15Nx=Ox`}ZH}%`(V<>K zC+snr+{<5?M^nrUsvj$TbIbrDcB)hB#oLt%Q%If#p_T&T@=S+~?J3!L%5~smKi>L| zb0>~4T$br_!^0D>*u`ord#W4_@a7l5hl7Y;FMO>7R)O8oCS<&5@gg zGh5_Ygr7v04a9p*>2j#RcTg$b)~(eQFy4h`s^zlv@B_a)4UT85vJjx+=7z$ATttq! zC%OGFk+tYQQ$l#^A31TrfQlD}8}gOHEfuvf9szP0L5SJ0@d%b-FcvCefBsb!Cmdcf zNYvoTRdu;tFj~T_0#N+JMczE9zxlsNB~!P&%KC z))w2nA04Qjv||yz(eC~{=l*c%qYq?Nf6q*6!fpHrwkjoj;HYU!(8bL_69$SE?auk6__@!@8kmcWOl~ z13CvGK92^w9?#v%aixK0RoDP ztek)~?-*KCwcGbshQt1e?0RS;z8KbTpA^y;MnFqv)ZVLg1I9#2V)UU{0LlqU{KM{r zS-%s}Crx?F?om~4RnyKRva^so(e}RkCu-7YDC3W&C%W*bM3 zZrC2T;*xFfKJGI0zk-X+gAV!x8qw} z**XR*V(VyxR}(}%gKjt1r!6T2RT3V0?~%>%GwPoCE##;o-vyp>hv!^~=XOro38k}9 z;7Iu%APe1KsBX9YMj&i0d~3o9-3#hN_^hcQ!mU@Ll2f~Z4yVY3l4iV;Jm{zahRzIo zmxQ?nYdyl5V%B>1_bh>-dMo~qU_GFDu6t(#kpq)>ojZ*J>y;s}&&(G-R%&H9S8J5mC4^-w$t$VBwQQ#Qoe-k>Z}wle^*fB6$U?E^tPy$FhzTD-bCcdo z**S0swD}tN!Weod6~T7L=6rQIHqC5vErra%1F#)j$e+E7#zSuG@iH~&M*(eq91gms zD3iGE^S#=LonFJizk6zkO^x7MLY%SFhMB*Kx7dKTR_WRwO;MAIjt;QAp`Y&agt6)o uj%(G)8h-R8Z$hF)-hC&%=eAcehHI%JZ9cuF_K>{yr-q~tbzyW8@c08{`UMOC literal 0 HcmV?d00001 diff --git a/_images/RSegment.gif b/_images/RSegment.gif new file mode 100644 index 0000000000000000000000000000000000000000..8c51fe97aaae1d8760050721276cd15555dcb82d GIT binary patch literal 2179 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

j`n@?<8-(!|EC9 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 P)M~W9=tiOJWUx2_ApigW@Pxqcd%WQg zh2j{A_rc%oY_x!Yfa+DKKtMpiz`&rOpye-><~N!9;P2xfjq{?=s0Lx`RjJYld2j?l z5D*aX@bEJ;GvMIh4gd)K@AvL>xcSiMj0I6D0T|~#o#r-~>}9aF2Wjz>$nJBv#0POk z0w`c$U>pGu%*@Q|T&(F$q*MbiaBy&tkdPoCAoa4>u&}UV12|AnP?`o=eg#SY|Nj60 z00000A^8LW002DzEC2ui0CE6A000L6z@BhOEE+jJvbZz1{j+s*VzpZx#9XU1^o%! z0I?gNZTI$B{#G6#F?73v>{!e0awLz=Fo0Mav$hfb9cK zIno%W0wF*P0HiC=9zMh-Me&|u;w8`#0U2;2 zf(Qg4fC35#ARxkC0}iwQfOVOuA%zRyWnxi!pA5hN0u_wF$u0zhP(cQ~To3{U!(@Ph zfFtcCA`~6Gg9!lF1jx|{2YeEO3Y%1L!7wrkc+CI@rlDW}C1^5|Qyg7Tfs!I@!oZg) z;>gj4eNBl0f>#=#2{tt$;9@5f9I&G%41~~^oqe%2z?uOh_(XGVW&&qN2r%FY0SAPM zCz)s+;1*hNZjc5IQAAWI0Ec!N0sLP})0)PUe z7a(9}R0A*t0AX@H;Q%~u3Q!XReAXEu02v&x>i`EZIRcXugh0Ro1YB?cb_gt)!2%4p zNC66s{&Lm{0>}XWKr-AlG3=(Dj+3V*OJ;(=0n0AXVouIx;$F8t6=jcBHz5R2t1?UGXN_1 z%;=<0De#Xl$prfZi7#mK4~OGStBI5TZre%K-P+4@qIk|(XIVF}ZIgU}29VhkEzv@x z0LYC~0i^hvdVt>_Hx2*;F|(-21w1303AANhKyydNC6G`lM!P4`$7FRhf(R-Mz`CtA z9&iH!*j>*500FA%;$;XU=vYCt6lCx_?EpBLLCiOeWC8#vr_qQM?|?TkU>!w>f(oAx zumA;+13&=*&u+rKhY;3YQ*{k!g${dF^j4^GD|9%W*a>v|U^51N(VIZyqN;P#M(9jeZ8PXVNeH?gR`vL%hOu&zVkU7CWmUkL8n5_ye zIUoT3!6gtzMFH1nidGz0x-5Jkg6El_3vV)j2mHe=ETEwWxWEU+yhZ>m+~GI|aE%09 z>n$|Q;8)V%pYT{GiAwAQJ*;AatYBb$h-g<9dIO(Kh_HTHf zC2IWt!;L$%08an|ISkM+03MLz7J3r^yKIgv1?b*@Y_S$>#K1_JNC89E00BX6VKvbh z(!?4g1C5l&7E>WWKd`X^ngoS(YiQ3Mpg~2&m@x)2DZoJ#`IG@ng&+bUh(RV`zT^nS z4MlNA2VMb!92m}nCU^i_vO$oN_~Mzqh(SG=(hmaUf@xYI!5`CcLPvDKJ8Lk&OFE&8 z6F`$6%}l2?bzzef@Sp`?WP=VOzz!ow;2moK!3JDOA9up@5D;KQJ(19XVX;AIssm{7ikz+?5j2p%DtanRRYX7nLJg`MXb{vI VICZ8>&8k+n%GIuVl^sC<06SL;^lShC literal 0 HcmV?d00001 diff --git a/_images/cent.gif b/_images/cent.gif new file mode 100644 index 0000000000000000000000000000000000000000..c2db0e22f877ecfb4f072ce76abfecd2ebe0acfd GIT binary patch literal 42765 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 literal 0 HcmV?d00001 diff --git a/_images/compatibility-scheme_2_02.gif b/_images/compatibility-scheme_2_02.gif new file mode 100644 index 0000000000000000000000000000000000000000..f29631d135c626000ca156628fd505554e36caef GIT binary patch literal 1342 zcma)#{X5eM0KmWB?Yr4nY|KnoY>dcqOI?S^Fj<+!)ixwj1+*&Odn_owHia$g7meY28EzUUyy?-8IDu(+f26*=hR$zW~{xDz3^u_*FD zLSmE^RLVP-j*{dR$QAY02<2sEjXy?`U*(Fi#Mb4atuP5dE-C}vCC&hQZuZ{p!rr-i zZ}6@r=S;h`$OdcCoeQ4pls3nn0)BPrvVPWKq#>1-iu4StdeeI#{fRiU2&%0`qWkgV6A_40*bnV0tLqZC8#96AXQ93ub#t0?cB9R1G7} zd!Yq%yoVUcc7p(csIMB_=;I8)Ga*b6IbVyDp$kEnfat`l$-m=HLRk73nTe5|Wnlt> zr>dvGm1yD#55btWp^axHb01B5v^JJ<_=UHl;cyBfa(TMOcxleU3B`HzdS=)4)@tg$X_Uh^orO(0&$7w)T=(fsYc#eUMax!}LVCTIGwDixTz|{Pf zG7UbVQd_sn{ng)d;~$1k4SFo@1l0xnj+ZRtnrljD% z=X3Abw+858gmSXvH#^JedbcXRq8joVs1Q6xj;!MzaGF}JiX-ho=vtqrpU>f<^Nu{`46qPw*_w63BRuiwM zq5Gp&$)4RpuQ6UBQA5r!dn`)JwYu07L-dLmAqVA^Jo-w@uSZiq5`V7X!cAdB_=p{p zNLWR-ApYf|A*S}fB`&juLILj=Yd)n%M-$*b!hI2Q_u}iinZwtNDajAFt9|?U2s-2R zwM0Rep@|W0)J6HHTX7t-WlJYrc`YcwsW&1svg=1m#5LSOo+U~p7JZ&~t%{Zp>H~F& zIX0y)L7_*sVq)NCH^{sZ=aWM@TOObgwGA62Ly;xiAhT?Agw09jP=_E_o0(f1I`fQ7 zP{0HYjWFEjKKT(Yybz@D!Kbmm9sv5|jxonwhZO5AmE@q^&Jt)DNd*|{e8;ibOkn@j zgGIoN6?7psD8U0gFcJFTeFPRmVIqmK{=HLjF!6~7v1z_lycCVgGHF7`g8_4(sVIIF o{gj~#{sjZ)t;WeQ;p|@98k5L_Be#s#^^&?x#f;ey3;=BY2bwW3=l}o! literal 0 HcmV?d00001 diff --git a/_images/compatibility-scheme_2_03.gif b/_images/compatibility-scheme_2_03.gif new file mode 100644 index 0000000000000000000000000000000000000000..b0b439df3a3f25cdacb5c7d68570a6c9ba16e4b8 GIT binary patch literal 2177 zcmcJK`#;kQ1AxD~Uu?6jxz1%nxh*EDmEyaZYc3;-$h)CMBuSEwYIB#{lvJoD5+&wR zbT~2Pl9CC9E@wpXmJ^PO(`D~_-v8l!et3R-KA*?c-G#MHFb(Vj#sHwJt4kyjfgtz_ zYqq$!s8lMMOr}DipwVa&iG)Zb^7(w3OeU2|c|2ZRT-=On=+C9)X%_Em_rSdHzUVZ*@rMW|C?({J+^K)?p001hL>c9T~L0^OaFV6VK|2zRm6)1^w zW9Sz4SH(Y$*?vt?li+b@U&DA^;**8sPNgi#)2eJ}t|fUew*8OAwiNG%SD#lqPJgcF zUPS;H94h4yNy8fs;4lC@(^rEC)Az!m4NDENiKvWd5(P%~gd@vJf#bOne_bsYjOYce zHH02V)uN>bNaQA%C(vqmJAqKE?kj`oG`ZzMAW&>85}17T8h9XV?+|u1H|DsY@DR0{ zR{WdA`hx?tc%NsQv|(r5Laz#d#gjpqRD>8MTi_P!sc9LI`osHp)f^_4X68lX@Wos) z4WY{nBu;aZQZ*+%0+cz7JX)$w;{hq8#O zKDVRw1+R(Al~2-fb@XQ2q}?J5xk=2pM4bx>p`llyiu=!C{=qN7cD?|X*>8x|mzeTf ztq^EEyRIK5&`f@J#D48_nDkAxgBST4yuD9RCxr~Dk0XworVgR}RYrU>&mN?#LmNZj zI8K~CfY`Ap-c*T^za|5AN)Oj^Dq$nL3-FQj23wE9dE5;~c>)Iz32A&PJV8^rHlCCcM4pv6-GSjbA?_+~d z&e)-fniFtIq(N25(GR5Tc@JlsGSEWfeEoBC1jIX8e*088wsfExgFld02p6=EY^^nm z7TmSkPDQ{BwTY@Zjn3;fbtH1^^gF0pN(Ol=CVzIwaXMA+f@` z80pA$p5Qx*)kw%+kB^PlaS_`_#;4h#M4GL(A=NjJc-|~K1F*E10u=GwmUOf3khqB4 zfD^;F`tXi;s9jY*IY2}H%s;+iS2#^A`Q=F=2)#{~gOGs$h-m2Rg`HKX(H{7i#^H-P zIi0(Fy2L12p5HeQhXzU$`OIwr11(&~eq7{lVl_9-*-1Zf)RG?I=NGV}*u@548Tkm& zLOZQmzLr8Wn|D6}>@tbL;R6MnTo<|;I)S!1#_|>XgQCUQ z6)tR}T%m6Y$T0Xu3Cnch^rDng{syYqkdjcLj$M6{(og4j6Tn=A1 zLrq|X4rx86EE{~5C)BbTphqnqRsVLG69rdz8c~#VNBA|GJkHhcR}*FroAbWvQr7O0 zit=Q8Q=7jLL-rx{_-`wmoz(R{Yl`OFlWsKq*Y25KHgez4qz#Q{Cy?R+L21PJ2uT~X zhSR`8e2k93Zg-12Z9KV%ocLXY9m zL1~^j%uNut=U6r1+=#F(tKpvbP;`ydPHXMA)AjVy$}lrc2ie%RY)WkM^N$)~mos16 zksFSIBK{pP&@OvcmUvg)rALs~1ktDoMUgVIw9z6`qr-h)u)H$_lU;8pii&_?Uj(^EC{oQ9MSWoK`dLV{KX z8%`tQk;R9?AX~50-BDH)OcRO-*W6!t$t7=NdB)cJy{0$vCy|?{IHu5&G@I`EKrfzC z`^;!MR8s;FD%q(z)ejl1oJm_delxlwIG1X^2N+rHWj$*wIPvtI!S~fZkkBN_@|-cE luJyZlH=VoqbY_G7+GAcpQ}IpDS&QJcfxu_+)Kmbl{|{T=Yy1EJ literal 0 HcmV?d00001 diff --git a/_images/compatibility-scheme_2_04.gif b/_images/compatibility-scheme_2_04.gif new file mode 100644 index 0000000000000000000000000000000000000000..3abc767185744261aae495a0be3849a3e183be4b GIT binary patch literal 1314 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 literal 0 HcmV?d00001 diff --git a/_images/compatibility-scheme_2_06.gif b/_images/compatibility-scheme_2_06.gif new file mode 100644 index 0000000000000000000000000000000000000000..a55a6beefbcc7e77def3418476058be46f9fcb80 GIT binary patch literal 1620 zcma)#`#anB0)Rih36h8;wMbpkO4KD(yEv_tR{6%QiguaOnd(I6>_J(-)GWv>a zNB=MO`OAMjfu)(|R+gIHkaqQY=5K?D&vb6qJooxCZ`rI5_c9MQ&a~x5 zbtI}EUCW#JXTgv`!;RTnH*M@OkpO8YQCJX=KsMm?ijVpKwu#4E0$^o}PrwuvLGdV@ z2wT8{pwBLVc<2I=A8!rWDu|UQfPxT+M_J*Ti_oI3?jEs4pSF*1>Gmb-{dh&qdl;-r zjR<=u0QRQVc3{8{tGIaR^ZF@^bBfLi?Wm9Y}C ze`yAViYULQ57dsz7O$i+O{@@H-X!t5?o~=av)x?USj96wu<0Lmyzy+#Z`-y%&GdO_y_!KvVmKRB8_iL2_l{J2}V1&d6tA{7m> zzi|xvg*x#N?f6I68e>buhV3aq(Hq8jmSHDWMMZSbB0~nu!96A+HgNu@SS&RBrU~Yg zGV}DPh4)q(DX1d%8pZ|2NHhx7VuZn7tbu}t@H2d0k)$W`Ty6b!^tr99Udsq~lB*!_ zw>8cC6&?U?Bn6(KgR%s06guF_oEb&gIw*J9_6#pP!$dgFKDQ_4(_2wiG}^d@?WSuh z5$^!&6g$3B>8nrXj*6@5NHh0$T#WMw3-bEuB)UQJAb+F|vw=EY@_dCu#Z?fB8TLN4 z=}v-3oTI4GD{kDaDwffjj(waIYAjo%(_WTIBP?`9iqj*odve89l$Tmu681&HZE3Zp z5=u!+?(eD@RsICpk>(1Ta9i(p1z>u9;Wrt2+TNtDUf&$E3+8;yp~rvKpm zFO-^5m4qIMN52Z6@}zzf`UykRx!T2HW;webzr$D=3f$eaoO~+e&pYS8A9X^1-yc8l zOAHGyTblG&W=WrTYqMYfcp`Zr<3VsaGW|HpGk=vx3%J?K-aXbK%&dCN)7rVj4+wl& zrHYWrNM`AaXKY4S$UYWXxy$_Pkn?Aqu^HH}e$V8)FDA*bQX#Y~;q)>bh+!_&Z!vp%hiUt1;{0xCRz@nNOpQii zCCcqvl=@`Zw?5%uyZzPdR)20&k{*s;+c?QI9|n?RT&YVb#pmI$%(~ejiLle5!YYJb zfbhTGg-M~$Hu(rnvG_!4^_W2P21hFOmuq1iND{9dn}cFaAsx0IB0tPVK6~7^6D)@ZMBj|7yLdR28^*bh_ZlYQvjJ LRnV6t2pswk-~F`C literal 0 HcmV?d00001 diff --git a/_images/compatibility-scheme_2_07.gif b/_images/compatibility-scheme_2_07.gif new file mode 100644 index 0000000000000000000000000000000000000000..49dfe98b06c6e2b8f1103426af2349e5fc011d22 GIT binary patch literal 1910 zcma)#{Xf%*1HeDqK4Y8BW=2BH^A?v6BBHY`nt8}%I;RKA`Bq#syDm%N!zS8!Sn_zG zArBR6m>%R+^Kcg_i4%8;aUP;ND%CgT_Wj=XFZjNHc>nZ%z20ojE>EvRGe8v33jhoT zL#3;He#`;TqEG}L$^usQ1b zc+<&&*D3cjN>T8Zi;rKZxK;qgf(WO0K~zmvPsL&QGd2PX0ull?5|NgMh(KW^_*^Ce z0ZNl1&Pm}2T?C<&h>HM9^?a~D9EIs5Luy1tI|~<-1gpo)kgydrI8&BgSF?dlBURS$M%l-^&sMeGgzJ!3 zBDRHuZRmHh{8>{b&qFef88|a_%R}m3h^MVf>PV{#Ul{=7$)Yqtd9PSwzjx>OwebKL z$)l!kc@pIpg&-96&=YMC;=?bl*jMTsg`m4oUkpa8wDCH)=`o6KWOsy_-Nd0m%lK1A zSg^flj_q#S$TmsWjTCJH6Rh57j45YnQY5}Y48*iR++r6EcCG@r1u9D|F(56*fQZK+ zXvFt&29SRg(_$FSYgT-s5+>KN?7aSbaN%s z*o;ayqxhdtiV2f!R~7ANR#~3(!yrPgbdlD69S{!tpj^l3ID{-52B;rcoUbH}QdVl- zxstx!vsM^H91DQPu^r^aIPJ-~H}ags0@FBjvkTdfUde>Nxkyg08oEy;P@vZ>rF)o; zpvxqOCyq(FW709E_@-GOaLQrXHkWX(+YX=IWqr5$)aTiIUik8Z%CHjtP{6#-8{n7J z9m$fmUS_Vi_lLA6F$wFFGFlQ{3%Fjlo?-}d?A?NS1MarnLUP-IB|Vbc@=Nq>T4*;N zTVZ!Tpws0UX=_+C>G}Rn55_0j=nmWAg$&01@7?Hh-_)Ldd%=|xBm1?~8}<8Q_nST4 ziqW{F?z74E0L=5vod+Yc2p{o%g)0h!(=AjFLa5u4e}{wlLGiOiy36u!@zHDj8*&>y z-oyhUZ;`=;OAMu!h@4HBnh%Zr+F=O-A8jMbTIElP^o8u(V?U0q2xmF6)K@Q|%lKEX z9b;ei{7OHwTe9o`R_%Q7!|@jHc4kv9(yTC@knzqFpT6bIW_e{>pVX$S6HD;Ze!(3J zO26{nx07Ab!>EYP9Q7Lidwr(#E~OX1yX{+6W#9YjK;UU!*<^*a{~e%JaT@fK;|1q4 zQL0eAzMu?*EynY`fnBnD*yOrrjZ2)t9^DkslLLf7L5hrju-cD0 zkE*|&$)9H(mj3%FzDYbl=$P^S)5Op`>H+av;d{q6r*lh-{mlx)!g7U=5aoNRX_*&Hhu0HcE+Zrpm*oR~cD gY;x_xO*KIw$PSvAG5vU}FGL|M9oTOv0RZp+0J*FjIsgCw literal 0 HcmV?d00001 diff --git a/_images/compatibility-scheme_2_08.gif b/_images/compatibility-scheme_2_08.gif new file mode 100644 index 0000000000000000000000000000000000000000..aeb572cce60b91d8a98f1e6576c95e4845514c57 GIT binary patch literal 2236 zcmcJK`#;l-0)W5YZDzBLZ8o{3En05n5~Z87%|^63Q!2S+6HZi`OG4^=F_%S|OOneh zc{?RCB)9U~%B|c34&*S3i?693b33vm~0idO&g-)kK z5HzM?DwRs{cs!TOwYIkI>+2JX#WI;prBYES6oEjXR4REq-Z#b5mANlJCf-asaHm|3 zz0|Y+n3SV5bNZZf<6Th9Y*g~nz>9^Nhi{LZ{8Cy80Kn?%>VN(JgSw3PU)=I<|NR6Y zSLtHG9!vd<$!L2@W_oP-jK=(`m-QoPLQH@K1(V-7ED6HgHg8W>PreP|{6gc*9LGZS_bQR*I2{rT)K?q9? zj@^@Jx0!G$O@4h&t}F6vkspGG2Pz{LA2}glSjpU~Qdg7IM~7+0M=8&_b=3S5hOiUl zC7u$V07Us6NZ^8*j?6#JDtB%|ckt9#2At)fGA4Svw?k$ZMPUK@j8Ntj9hlpti6_4PkkxM`Q|Ncq*n_>B42|-yO}O;L{r@m<86xXXFw`sEZ`i*uKYtlH!X}xrklA({dF0FHbI>0>y_236b-6}D{0_kw9&A};)Jc< z{b}*c^?!FaTwUV>sl83l`n9?PMU)L-qpo@~&J)M7_$IHAYZ({YRc?i%mufdv zlDOG3K2A%S1fRYi3$?HLD?}~Ydg(&5#pgEr$2wsq<9HS%w<7q(eoZ@E-KmDH~Q>B0aN^0MkX~ld!2kJm7?V-9r5wmENd7UH9MKfl#7(YEnX*v=l4{Yyd;@osX!QWp;0?$E<8(`0sy z`$M)MnxPbZOr%^?idjvBFbxM^J!SLo3!D6dK2)Qg$kAGTcXwuQb+I6rSZLg);rAAX?3qM$J5>x=F+~v@xp9 zw6Y@gjf*K(%MH|QOk#k};Z!=?HXb;U{inqw@YI-OfjK>1Y*6>r&GN|?sJt{#wUAop zOUy#o8XmWbKy&<>A~$Djam8omE*L23KY0w5c5YsATBXj z4e$)-jIo9sszwnJ;g&_mq*IEKPDDT%RuU+lCZOoO8%DJMwKS!Ghm3SvMG}vm>D z8tHW{s{mQv@ByL_;5Zz>JZ=c|Azn%r(fA;lov%|VcCTFK;*8je)*ca?Z|H8ZYPj3U zEkjV1SJw4gLUr((pb%mHl^hMVOYHBCV#n>O`zXifOzyVKW*EsH=aO`dl^cnT9Z>+t zR5Z9`mhG(yyd9fb#=8}(br%WT^?Fmb$$vdo*2XAj;s>ms4isO1lVlvwI0~BwUT``S z?onj3zP(wtU-j&RL*{PvH3v4z)^F9p)vi09#(h{vJIzB!hmfE6OZb`EnipEjgYI%A zV>9M!x##Z~Iu_I|v!gJ-d4D`vRC>@xHq5BSIl+Pql1JM3bz!#;gvuMB{JdP9=G}f_ z1_Gb0ac49)>yOY#-jAlLsg2B%PZ9??dAo_F&T#r;`>9Fa5Mdn_(=i$%_js1<2cFb? zhii#_qkQ$LdcyxFb(4#8lhE$yV)GEs%zDv#e+c$k=n#F@2KiL0K*er$zkw2N^v^u5 zOOyJEXCrGGmA7Q%>ZNXx@QyJ*&8Hqm&_*8G>0=dxd(gV+US9X)p%hZPe`_62@CfN` zqjukp+SQZz!MJxglOTp%i zsyEgdF&N73EwO6lZ?`rrcMGo66i#!dcZ@CfMEBH47Q3b$e=PSxn)jvZ`%X9_Kw#%z DJuFKM(WX+u7OKnb~=}v+s?AJV2g; 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 literal 0 HcmV?d00001 diff --git a/_images/exportmenu.gif b/_images/exportmenu.gif new file mode 100644 index 0000000000000000000000000000000000000000..0e50bac6cd4334ca85e9b1a24dd4d2fb78b5a050 GIT binary patch literal 21453 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 H23-CR2+)dg literal 0 HcmV?d00001 diff --git a/_images/findglyph_fl.jpg b/_images/findglyph_fl.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3112dd498aec8b6ea4fc00cb5976523b82e04d51 GIT binary patch literal 8863 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 Klsuq39QhA1LAn6| literal 0 HcmV?d00001 diff --git a/_images/flatten.gif b/_images/flatten.gif new file mode 100644 index 0000000000000000000000000000000000000000..6477776b273bfc3a6a56705e4eac5137ded62944 GIT binary patch literal 5066 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 p$vNTnxX-=rchCFY`~LU955Dko(6Qnh|MO zG5^b%|N7r2P*c(9IpI;aBOC8VFUVt-1H&d7Fg6ygA)@0?M#0M# zn(gDbUO(>?5p>t(dp_vDg;)Cp>p{HG08jwt|G)`RzQ$u9vrOsR9PWPo7Y3>-C8y1_ z(A}QIIu;sIFj&@vjrZ!NQGcu~#}9c?B)W>~EONag#5EkfqirN5ODK&2OlAP%@qi9N zsDtKRHq@VM%Eb8gH(m`Zsuy;|BuBfGi>~R%Bu+n@x-mM0-X9H87e`HZ%{*n1R@a}> z$T`00CR$-)nSj)nXMKaAGf<~Fbc<4aWv*R)UU8nlDhYVU7Idg@b!2Gt+WcsF-0`rz z60u^~#A3$v$ApM4HRW@u%+mK-GCO)w7c3*OS_!!zHma`0$tZuIp|4H;7EIa3yktgx z!~He(v87%Z^Hh(${)8)@Hl+PG#`(X8CDmp4B1dt>UMS^@A{BlJ=RXN98^k<2j?Sv0 zLg;O?i23f``}x}B#ox(v0!MKIN9dZ%^HTr5%KwXL3QHe@W(sG>y93&UiC+zMiv+qA z@w`k1o5830e;1OQO@^Plc(b`K(_3)52+9owXP|P;bo&pX-z3p>TNi-@Q&sB+be|;VRkH=@-Gc zRKO+Hn6M{IYUz&1FNBOd*}TsIC$SC@s_!--)(I_m&>0Ist=4Y^=6geTlO9Yucgelk^!MWC3|G`vp_Q<#dPYP36oVz8OY%;5a$93R){Gb%>M*tUG`6o-zi9IG=Kk(I46Rn`b;VQx4Le z=sHh|e%K-PNbbZM&6OKn;2_ui4C1_k0I5EAWFRBdc)?$LA>s8f=S4KnZ~JTU=@)jN z)3`|I^}?_L)8*2S@?DOR=utOfu;}@2j<_h(P9sEWI1T-TMTd5HwvKvQPx6`^?tu=9 zZ?WP&;pfWF3qH?OrsEa`8+O^IC;kXv?TojpH3OK7?MavN~J2!m%LntKb;q0$qHPA*OO4eL{?qs?@ktsv}8hco^`{86V+yy*=NwlzVm$ zh7g4F@E5&OK2LR)(eULf`byX=c4K4I{>{9lF*QF6shFVf;_Yyuxz3WOcwz zW0j{LqAB*NPs%C5)UMXDvKzckd5qnfSgqp>JHr6%`3Jz|%*Fr! literal 0 HcmV?d00001 diff --git a/_images/glyphmath_examples_02.gif b/_images/glyphmath_examples_02.gif new file mode 100644 index 0000000000000000000000000000000000000000..b77c8c44833518d369198307bcb10f1753d8fdd1 GIT binary patch literal 1105 zcmZ?wbhEHblx6f|IKsfd&c=4=;6Yaxm*(c?4<9}(UbIMDOzh#qhbbv3YO1OiFJ3e= zHJvwN_}=Sy<$ zSFC$q^Zx&V1qB{DQvD~E6rIemntx$MiPzew^*7d(oqk)j|G|a|AHCVy5o45P^ zhaEM3>u6d(PZ>^A{{! zw0OzVWy@ErT(vrsg^`hYBlG$-X&ab!>}2K&;o@OpW7xsFk(Y^^ft!bYYaBZV8#gcO z`t^LgoZO85EIgcS9IR(F`8XJOS&0XskEo>yx`JRBCx zW?Pp7Z+w!%Cu>C5#)7Rgpp^-@9iy&O@iy#6i!@Ckms6YU!8Z5b77;csKvXmSHvR1?7$u2m60qPe0Fck zWw3GIuMof&>BKnC^+?#G2XC`Q4~L%FcUES5p7{AmAAKj<=w)136u!axL5W+b$ht?J z;`e`8R%9^GkTvMlcFcWv(^n?P&)S@uiJL_x|Kr`72{SpC1Tz>N2uv2t`Z(1<{(tSc zogW-x=Y&p4-bT+YX9 zmQ=X(6gEC?@M=5huE?pq>BfR?C7urqERK;O$~EpOrA&4=zpi-DudFfQ^wfxFlY}P< z7_c!G=-!BE3DkIy(KJQn%W+jcp_e_|S{yR1_n8BEkF2#6a6Nt4$7`LzS?aa!O39h>JBE(2^&HV#>sDDa9*wIP~r9K$BDGA|J^i4LW_MZ4{*wB&|dgJxfKld{Frsj<35eNfJ&9Zaw6cRyNc!WqX z!;=xn2|{o%C{Ez(0AUj-!wky6s3Gt)(GB;JN`U|TBEk|gwONEH z!0DFCRt*)11n6=b%vox%zfdq-j`{9CmKgQu_lJs{C#~lF;Rq(xw%s_0>9R1t>#-~V zFDZRSgiCImx#iy#D6IwfqZ#e20T5fU|s>*L|q+f zMbCray%EzXJADOenFkT%qx?0}bul;+U`>pSF9wU)l?2*uWM8(4Z8#&U`{Ib}aYy@r z&63ZrBu|h!8_W18_z0LEg8UY-x4=;szJaf;x-<0TbB8s#m1Y^Kx3$6#x(iQgmmoihbhqRl^ zEUvzjrL%YZ?FUuo3s6k#o2BE~g!#8Tx>?Pvte9k}QeN~baxy=5c%r_Rn3>;ZU&>Ow ztnnm7KkiC^kTVQYpax%0N!!ZYMG8rFy4IN7gqp7=cnca-C4^3<`?2!}hwAILHaAev zV8qIbI$J+lCauW;h4Na5#^K+6sG&6j%?WsoF4P_dE#+0R~U)|k#*EErY z?NNVycH28Qw|DIW6o`!*EuP<5IiK&>??~Dw?^ef1CqmX1!B1;dwsTdv~!rf(9jdFk5X=Ss|8Uf8ic z@MOYHFaKKJQ=@RnbYfyOyI*q0!Z{-Pq}6&QKY=)=iU2@2WE=L>hS3Dp70>l=7}`IU z+ACp;zMW-OPEr&(S?t&E;j*oU8Q?7A4`# z6D|nH`K>pjjhnT+Opnd2;$V8@$hs%|?a{tu$wKU+iDgiwJ>W1r6EXxB`3o0lXuwRI z$(iycJnLI-#r1|&p1;JleMk~k2yaSm$RmU6d12?Xb8@ V7r0@%xG2Axxgxl0Qx*VT{{o*}T73Wj literal 0 HcmV?d00001 diff --git a/_images/glyphmath_examples_04.gif b/_images/glyphmath_examples_04.gif new file mode 100644 index 0000000000000000000000000000000000000000..9f00d6258ddd7907761961ad72210a6fc0165637 GIT binary patch literal 1097 zcmb7-{WF_)0KmV`lNU)mNxXCwrmCF^^`y%6MZ9eB(u5eJ)T~?=j#hhKGRNj{yLf+( zU|y20k!yoeufx!qJ=A-=WacFuCf#b>CiUatrL zhhzWX|I5+0e)|Ljy|s-v=DIwtr9J-nkPw|uN!Unh-^tw3V+x@!YEeF^OrDB&tykYo z;kRAx(6oN8+D`vo+nM&^shjgpd(vkUA8hFQGXpzTcm5vya(?HvUX+!clbe@cP*_x4 z;snHEd}-xnU}!+ElhO?kLREb*saB?xA{B~eUox?wT}r&$((Os@=&S4MdGJ1HfMBW^ zrnFNAC*7br94xmbsFYx8=^Tj;&D)R3CYF=%R2W(yLdfDp8Viq8exto!O(zb63P42+ z45$L6amwGc?NK*R;$zLgv?Y!KFNkvE3nEcY*w!@5kW(hg%D>`EmZXiZXG0VV{b-J$ z%RCpxEq-R~_X-)npEN-@0P++`WZY%6+k_y3DrnlZN{&{|rldK8X2Q+JgpVFuyAZWo z2!5_Or4UeELyQBp}kzcV?{G8e%9doU_MM_yHnj2sJSd<&8Xfu@rS+eVtk zH!#(9r)=sT0+Xs7{)&7}gb1_8-{D{i%jV_sV9l*EKVH<_g(e%}=wQcO$YHu-ka;h8 z-*k0gOZ}{epH*crO?A=z+!`pSB1YH;cKy6OH>EBVr;qC{Th5NaF?4e{%GW-EPhaYK z)Om#H^WM+_yH9F={xn0D!(s?Ii6~n=Bak>@OW=Mg2}*Kwj{$V6iewFyjAzEMDMLXR z-^?6~3cIz=_<=%PPOYVRSezTj74I!!;<#R;69_HFYqPNKjomo(UBoscrwK_`dD^RpA7y Kk8unDw|@a?+{qUJ literal 0 HcmV?d00001 diff --git a/_images/glyphmath_examples_05.gif b/_images/glyphmath_examples_05.gif new file mode 100644 index 0000000000000000000000000000000000000000..e6cfc4767375d3ecabc5cc6513cbe54edad06910 GIT binary patch literal 3183 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 R+B?rSI?w(C6bArD{|kyUmS6w? literal 0 HcmV?d00001 diff --git a/_images/halftone.gif b/_images/halftone.gif new file mode 100644 index 0000000000000000000000000000000000000000..4eabb652aef52ca9683f6a13dbf3dfd755cbac6a GIT binary patch literal 4771 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 literal 0 HcmV?d00001 diff --git a/_images/logo1.gif b/_images/logo1.gif new file mode 100644 index 0000000000000000000000000000000000000000..91428d5ec654044a289e0c830181457e8a8a0342 GIT binary patch literal 3406 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 literal 0 HcmV?d00001 diff --git a/_images/message_mac.jpg b/_images/message_mac.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8661dd4e53820a9858ca1c9cb712895644a577d2 GIT binary patch literal 23113 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 literal 0 HcmV?d00001 diff --git a/_images/rasteriser.gif b/_images/rasteriser.gif new file mode 100644 index 0000000000000000000000000000000000000000..6c2e55765ebd07dabb324c0c71cb5cbc641903a3 GIT binary patch literal 24922 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

vjkVKX;|bI(`3+)>naeg{g0?3*+9 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 literal 0 HcmV?d00001 diff --git a/_images/spike.gif b/_images/spike.gif new file mode 100644 index 0000000000000000000000000000000000000000..72686b11666c988fd92c7ed45e25d7c6a0a8dd53 GIT binary patch literal 7473 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 q=Lx~m)AeK3$S;o^rGYMCz$O!_|!n?T|K literal 0 HcmV?d00001 diff --git a/_images/threshold.gif b/_images/threshold.gif new file mode 100644 index 0000000000000000000000000000000000000000..39b05ea5402a4ea9f5764d0ca6c5d174c2beefd4 GIT binary patch literal 5111 zcmWlccU%*P1I2ITE*FN}B?w`~3xrJ}0To59mw+T7;(@5BSOYFp(1578Y7({zB&dKp zLF(299L3oSf|J&Ow4$O7IEp)NXl?WB@1OVQ`{#Y%=Y5_$A%4u*OdIe$@C5(}f(Q%@ z6pO{q&dwxBjvP61(xgda$ByN2IIga)etv%L?(P5pczJmt2m$~%8X6jghKBz7>#xtB zKVQFo{hxpS`TOs`KYaM`_U+q$|NZyPn>V$!wM9im=gyrQ930%edv|ehaYaQ%NlA%b zuiv_L>-O#2|M=sNKmYvm-o1N!_wL=fb7ysRbyZc>Pe1*1>C&YeH*P$8_U!cO)BE@D zFD)&7{P?j}tKGJ3TUlAz*RNk+zkXd;SNH1GtAhs*HZ?VU`t+&4zrU}q@AmE6U%q^K z|NebVO^sTue)8nWp+ko%D=RxYJ1<gzpY&mx9*pEN{c<0WYGiT2H^2;wzpFTZs;J}L)FD_oZ_`?rBG&VNw z+O?~vr{~C#BW-PMH*enDv}x13ckirL>&urfuU@@+>((uk$#nPb-PYFD?(Xg@SFUW{ zym|fl^(Ri8XlZG=fB*i22M^lY+fSZ6IWREr`|rQ++qduN(WA$YAOH2&U-#_UbN>AK z!-o%l|NZyB{r20#hYxKw+u5^cdwYA=ty^a{n|JKkaryG)=H_OGVb-o)yJpQAi^Wo3 zUw`VzGe;m0Y}~kU_3G6Mg<|^j=@TYQm^g9b z;>C+)GTEwCtClQTvS7i2n3$OO_;?Qw52;j|n3$NCmp5(Nw5e04E?l^9_Uzf2nVIS7 z>GS8$Pf1CMj*ecweEF0qQwjSQmX?*3m7kwa)Aac9<0*;?3JQAp^3P+( zj2@d>9G|3Aum&X;V{kef^%s#)g1^?u3MU5fKq~`=H(a_w(m}=H})W743Wf zeo!L0;P3CRQmG;%BU4jTlarHka&qi;yKsp0AKm~E_J8?*CjiV2*g4(`lfhhs@j^1L zn~Yb=aKFSoil&D4E&QmZz1N!#T&pHyH+v^EH{RG5H0@}{jpiS2)rsfd+>>zX;4iz! ztbEZ{zWCa&`#E>{(2K}UV8)gt-2Z4_M-Xdye_{H%_s$hA3-M2feSJ&z@Y0t3Yr2wE zx}U!(W&oEowC{DwoUpX~%#tLXHuiq`xqQD452w6Ym(5vE6MbTbJH)p-v`O`0spYO7WO+e-mrBN+7`kYrH0mJEW zZBeyx9eu>4b5}=IFX$js~g%y(pB549x&#;Pp;Dr>&HMv97TJuH&miVdK7bvira|JN03FE?qCMj^5@BTrH z&j{ZEzCoMFrK8XhOlv_K{rb`mU~vTTq*msDAd#mN;N zrY?@&=@XBuYD2E`B3q73<3u!Wzv_^J+jo@umU7Qr!-R*Wu1=#=ic~kpS1oB=@18@` zJVBf9r1anxx&~RN7EjJi^T~Ujyq4*bWsEftQiX?tK|JMO-DjX=?~ZNU>AKMh7vY5F zo7kD;vushBb-SF%PhPDFOjF096C3WMY;H6nm3!W5XJQqT(=y}Mgybah9O~$0yIExM zK&LOz+ZwkPneHRXb{nFv{N|mY zOAL|s&|2rXt#rFXn9dOU&9Gj&%#$}J<%V2dJX9r{?r_a2nCdH+zAmVe1*BXi@E&l$7Y-L+HI z&K-eh%M)s@H(W>%Jkhi{uU7GfFSnWWqCS)>oD}eFGn}T*^}VcMb~Z!Jo= zJhO-jx=Cs%+0(el(p)LaMGjO%Z%rWr23nU0`dYmcWhE{;5%li`DVtxW8%7x&ecypT z_OJn+e-0qJZIZ`?$qVh`F_g(VB%ZTaOc9Rma}t;qXc3+C8iBgSBlH6xz4 zV&7(gYm~8Gu6l|y+AzABmU_(3xsFfQpuMnujIr#k^LRhZ$;U9^0 zo;^gsUmLbKsR22V$03&%a|&KvXVcI0aY+q+u~d;I^1XI)w#9Ewc3SK(u;RhOHm3p` zN4|?L9hcjP{o%mz$Z64!vS{?Ly)~sVUB&uQ3ov=N0$*gY->4L6!S4q!b{D5+%*RYW zcawH>L_f@cV??=zKU!SmkwZF33PI=hCb}}cTNp%3<3B5b&;cQjGpKg{OT~(AF*pYe zLf+pgS-}O2OQb>?#HU!kTg}cVO~oSu^xBQM)em-ld`8?~Ju63wgaKyfo;Emoj1Y^r zXt}j2bnkL2>Z^?7pQS+F$7LdUF6O?#q91n}geeQ;6=Psak{Vnbaezfy;6M?GRw#?m zWHpop`f-9Rls9xPRc|*LoyeVl(<7#M*jFPb52M zxZYRG@F77Qb~4>gYZR9w28OenD93n1*QP-s@>FwN>)gyn$M?0f zEAryMwV8E=B!n>~(r$cfl0_D|SwTVBol|wn7HHOCxQ3H+rz*#=oZJZq#PzA?B>{F= zbybbanl?|><+3r8)P+ya69&e?GYy_K%jiW_TMgTNGGW*^g@aNubXU-%;CQ1J4WfoS z)nD=9TcPn{Cd>Coo6aS_q@r>y>5uUgC#{)PTQ#6lEEBMrDjnAgA{&$x_OIR%;%h-| zIRsmSYXl4~tSWqa#NJdiS4D`1dn%LAR8i_75{wM3(#Vl1XZ!FAgN<_<}>8 zHv%CeKI*vgo@|f-MC=+&87>;GZUrbIpin3=_Z9|M>55ZC3^#FY91tUXrax`uouL)T za^{x%G=}G+h^-r|)r9JbGr3s46o|rwLw=@G&2Z|j|JcGW zcTVF)zKs+7k_w-v`l`Y1cny@Ctr4{1<&r@yxMdTEdvR!+Lx$2JASlkuYS9RsWN5}> zweP_xgn;kt7lR@87s6&VI0Jx3QX0{Fpp>sPJI*I%7^U9HJxrllwkvLe&eG^Tl;bS1 zOsq!&y1BziWIcrhDzVu%$Q->Pn1*Ho(BD#4j1IzW;o%fG+knO!*d1lWN^-5c2Hh!U zhgz_YAMk?=;Kx8)ZQv9JUZrH`16Yuf#kYcPhNTk;NuVAqGoT5EfFd04g-{>L&9;^WHs1Z$E&2(9#S}#2Gi8&fp~Z|4Uu9r zM~Qv|Kt8(cFdf@pi9G*}o2rAn%`9(RtC1jA4C{S5!P014z#t1%u2A6!9W5v{z@u>Z zL@AdCK&QqKK{WgtbDc*z*gg=s;zCS_XuAj@se~nnT#Z&K**D6#Ta~Ll^H@b<-eTKE z7XqA4XY)G|OF371W8wR+bLX&55we(ys4Lr%RAY20t(SR!mUK=2SEWn;v?l=I- zO~-R}tSNRC3{fir-XSw+#XeFWpl6d7c7~cY@Btr7vqn@96P1oLbX5W)Yp=E1(TMJ} zjR}%Mk}hI`iVjHulNm4uh*Fd5xqZkt&j~3l^=pE?EsmqE;Tfih0V$~D91&#*4-kT@ zZ7hwr&Q3uYTw?OQ?H&Y6PX~<1#C~5;Kf_S&r-4S>i1h}n+Mmm_z}WyO3c@D>)jVUZ zP{SUrgNC&d5dbHYPbirB+mUc!9icU?n^lfX5@W;H;8QGf2_u-~!BsL#eEP7ds!|sX zwr&kqqgpS}umV35%Sd#R4oOYG-2vq85xjBMicrfAPdyZ7SJykggV$-fNj9aA5j@^a zh;^blS6u@Ik}V%qI1fieyx<&!&!Ja!exPVd1Jta)nnBImsQWC}Y% z2mg0RdY<9}fE5MAd!%4;SC%oIE3wK)=uwW^VWAjXZh{OgxXoJNz#8b@T;h=Xu zxW)v{upHo~AgMOQRkwVYxrQ`4Trt2QN(Vm@_1cABqJV@Y1ebAoFCM1#;Kp0?*bpM8 zu|@QjG%Gzbou5)pC&qF;#O(fVZeKsV!~_RY@FD{yT1Q+nIloj5BQlKvd04QGHK7g{ zt3w0M5jNYfUZ#W;qOMuBMl`WR6!gQO3y*=bO(z6W^tH+*m|#~9%yk2t zJDH=sYya~>XUFAxSipTcq<=Fp%Hnh(3hoPv-lTIHPMi$ZgXI)UZv#UO(6f)k9DH@C z5xy1>9Y|rLIK<7P+;LW5k7>U^57WAxK~31|!04IE9lWOPup`&Q&ajSfxZ^DBU&^^- zRd7gRq_&R0O_gE3jw$`zP~EAp=Eb+y5uReGyT?bWM1r4i*U{BedF)Ud_}v=fCj&6g z?3+)sI2X8K3~=YXx5|K7cM?7{dzKRM$I<2Vsc}Mfw%8CMMKft66K~Gzgh{Hb*2B@s zb~?}a(*`ddmqv@pQ+b_iKlM-UoyaORYaPztx}Hbj&{pwrN(hD-n*50sGt}ARKz6aE zWpp1@V5*Iiutpgg1Et_*)4Z5G$o={GXbl*ng2f+ra}8KqE!UHQyi9u~c@9qa(J=&) z&A=`Wyb_#qx0_o|u}3cAr2tU6ok~s9z;X&(Ig^({v6F6b<7xOi^^Zg*7)~7^Bw&nz z6Qepg`Q15x^87bKR)o%>fVmi?2gj2}&;LfAT!>3Rsf|6If(|M$)4T)pM0ahz zzp9Ps11DRcUX~=H_M9B6!3Trc8jdJ zH5yOEq3^6LciXW5HG2b&s8#4%6Bcd(=UCu$G4{g55s9JY3{vGi+LZyGsbbP468h^`f1^23e`6|SZhPL5YBmj=LvR7GAi3LhDVU-ML4qiQV rJ{Y7r`|LOopgRO_v|xKJ4wo!W4=uy~vEV+P+zFkob31PlI56&i1t!$g literal 0 HcmV?d00001 diff --git a/_images/ufo.jpg b/_images/ufo.jpg new file mode 100644 index 0000000000000000000000000000000000000000..294ca7cbd46e9327b1bef83e8b33a835ab37ce70 GIT binary patch literal 46669 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 literal 0 HcmV?d00001 diff --git a/_sources/api/gString.rst.txt b/_sources/api/gString.rst.txt new file mode 100644 index 0000000..520795d --- /dev/null +++ b/_sources/api/gString.rst.txt @@ -0,0 +1,7 @@ +======= +gString +======= + +.. automodule:: robofab.gString + :members: + diff --git a/_sources/api/glifLib.rst.txt b/_sources/api/glifLib.rst.txt new file mode 100644 index 0000000..067f5b3 --- /dev/null +++ b/_sources/api/glifLib.rst.txt @@ -0,0 +1,6 @@ +======= +glifLib +======= + +.. automodule:: robofab.glifLib + :members: diff --git a/_sources/api/glifLib2.rst.txt b/_sources/api/glifLib2.rst.txt new file mode 100644 index 0000000..07644d8 --- /dev/null +++ b/_sources/api/glifLib2.rst.txt @@ -0,0 +1,6 @@ +======== +glifLib2 +======== + +.. automodule:: robofab.glifLib2 + :members: diff --git a/_sources/api/index.rst.txt b/_sources/api/index.rst.txt new file mode 100644 index 0000000..9ddc87c --- /dev/null +++ b/_sources/api/index.rst.txt @@ -0,0 +1,19 @@ +======== +API Docs +======== + +.. toctree:: + :maxdepth: 1 + + glifLib.rst + glifLib2.rst + gString.rst + world.rst + plistFromTree.rst + plistlib.rst + ufoLib.rst + world.rst + xmlTreeBuilder.rst + tools/index.rst + objects/index.rst + pens/pens.rst \ No newline at end of file diff --git a/_sources/api/interface/all/all.rst.txt b/_sources/api/interface/all/all.rst.txt new file mode 100644 index 0000000..974669b --- /dev/null +++ b/_sources/api/interface/all/all.rst.txt @@ -0,0 +1,16 @@ +=== +all +=== + +.. automodule:: robofab.interface.all + :members: + +.. toctree:: + :maxdepth: 2 + + dialogs.rst + dialogs_default.rst + dialogs_fontlab_legacy1.rst + dialogs_fontlab_legacy2.rst + dialogs_legacy.rst + dialogs_mac_vanilla.rst diff --git a/_sources/api/interface/all/dialogs.rst.txt b/_sources/api/interface/all/dialogs.rst.txt new file mode 100644 index 0000000..f375a46 --- /dev/null +++ b/_sources/api/interface/all/dialogs.rst.txt @@ -0,0 +1,6 @@ +======= +dialogs +======= + +.. automodule:: robofab.interface.all.dialogs + :members: diff --git a/_sources/api/interface/all/dialogs_default.rst.txt b/_sources/api/interface/all/dialogs_default.rst.txt new file mode 100644 index 0000000..7e807ae --- /dev/null +++ b/_sources/api/interface/all/dialogs_default.rst.txt @@ -0,0 +1,6 @@ +=============== +dialogs_default +=============== + +.. automodule:: robofab.interface.all.dialogs_default + :members: diff --git a/_sources/api/interface/all/dialogs_fontlab_legacy1.rst.txt b/_sources/api/interface/all/dialogs_fontlab_legacy1.rst.txt new file mode 100644 index 0000000..7999368 --- /dev/null +++ b/_sources/api/interface/all/dialogs_fontlab_legacy1.rst.txt @@ -0,0 +1,6 @@ +======================= +dialogs_fontlab_legacy1 +======================= + +.. automodule:: robofab.interface.all.dialogs_fontlab_legacy1 + :members: diff --git a/_sources/api/interface/all/dialogs_fontlab_legacy2.rst.txt b/_sources/api/interface/all/dialogs_fontlab_legacy2.rst.txt new file mode 100644 index 0000000..9cdfd89 --- /dev/null +++ b/_sources/api/interface/all/dialogs_fontlab_legacy2.rst.txt @@ -0,0 +1,6 @@ +======================= +dialogs_fontlab_legacy2 +======================= + +.. automodule:: robofab.interface.all.dialogs_fontlab_legacy2 + :members: diff --git a/_sources/api/interface/all/dialogs_legacy.rst.txt b/_sources/api/interface/all/dialogs_legacy.rst.txt new file mode 100644 index 0000000..e05d931 --- /dev/null +++ b/_sources/api/interface/all/dialogs_legacy.rst.txt @@ -0,0 +1,6 @@ +============== +dialogs_legacy +============== + +.. automodule:: robofab.interface.all.dialogs_legacy + :members: diff --git a/_sources/api/interface/all/dialogs_mac_vanilla.rst.txt b/_sources/api/interface/all/dialogs_mac_vanilla.rst.txt new file mode 100644 index 0000000..d906b8c --- /dev/null +++ b/_sources/api/interface/all/dialogs_mac_vanilla.rst.txt @@ -0,0 +1,6 @@ +=================== +dialogs_mac_vanilla +=================== + +.. automodule:: robofab.interface.all.dialogs_mac_vanilla + :members: diff --git a/_sources/api/interface/interface.rst.txt b/_sources/api/interface/interface.rst.txt new file mode 100644 index 0000000..77ab806 --- /dev/null +++ b/_sources/api/interface/interface.rst.txt @@ -0,0 +1,13 @@ +========= +interface +========= + +.. automodule:: robofab.interface + :members: + +.. toctree:: + :maxdepth: 1 + + all/all.rst + mac/mac.rst + win/win.rst diff --git a/_sources/api/interface/mac/mac.rst.txt b/_sources/api/interface/mac/mac.rst.txt new file mode 100644 index 0000000..eb28675 --- /dev/null +++ b/_sources/api/interface/mac/mac.rst.txt @@ -0,0 +1,6 @@ +=== +mac +=== + +.. automodule:: robofab.interface.mac + :members: diff --git a/_sources/api/interface/win/win.rst.txt b/_sources/api/interface/win/win.rst.txt new file mode 100644 index 0000000..3a44a8e --- /dev/null +++ b/_sources/api/interface/win/win.rst.txt @@ -0,0 +1,6 @@ +=== +win +=== + +.. automodule:: robofab.interface.win + :members: diff --git a/_sources/api/misc/arrayTools.rst.txt b/_sources/api/misc/arrayTools.rst.txt new file mode 100644 index 0000000..3ab8479 --- /dev/null +++ b/_sources/api/misc/arrayTools.rst.txt @@ -0,0 +1,6 @@ +========== +arrayTools +========== + +.. automodule:: robofab.misc.arrayTools + :members: diff --git a/_sources/api/misc/bezierTools.rst.txt b/_sources/api/misc/bezierTools.rst.txt new file mode 100644 index 0000000..ed55439 --- /dev/null +++ b/_sources/api/misc/bezierTools.rst.txt @@ -0,0 +1,6 @@ +=========== +bezierTools +=========== + +.. automodule:: robofab.misc.bezierTools + :members: diff --git a/_sources/api/misc/misc.rst.txt b/_sources/api/misc/misc.rst.txt new file mode 100644 index 0000000..8158a1d --- /dev/null +++ b/_sources/api/misc/misc.rst.txt @@ -0,0 +1,13 @@ +==== +misc +==== + +.. py:module:: robofab.misc + +.. toctree:: + :maxdepth: 1 + + arrayTools.rst + bezierTools.rst + speedTestCase.rst + test.rst \ No newline at end of file diff --git a/_sources/api/misc/speedTestCase.rst.txt b/_sources/api/misc/speedTestCase.rst.txt new file mode 100644 index 0000000..e9c25b7 --- /dev/null +++ b/_sources/api/misc/speedTestCase.rst.txt @@ -0,0 +1,6 @@ +============= +speedTestCase +============= + +.. automodule:: robofab.misc.speedTestCase + :members: diff --git a/_sources/api/misc/test.rst.txt b/_sources/api/misc/test.rst.txt new file mode 100644 index 0000000..8dc0da1 --- /dev/null +++ b/_sources/api/misc/test.rst.txt @@ -0,0 +1,6 @@ +==== +test +==== + +.. automodule:: robofab.misc.test + :members: diff --git a/_sources/api/objects/index.rst.txt b/_sources/api/objects/index.rst.txt new file mode 100644 index 0000000..63e2c18 --- /dev/null +++ b/_sources/api/objects/index.rst.txt @@ -0,0 +1,13 @@ +======= +objects +======= + +.. py:module:: robofab.objects + +.. toctree:: + :maxdepth: 1 + + objectsBase.rst + objectsFF.rst + objectsFL.rst + objectsRF.rst diff --git a/_sources/api/objects/objectsBase.rst.txt b/_sources/api/objects/objectsBase.rst.txt new file mode 100644 index 0000000..6d58fe7 --- /dev/null +++ b/_sources/api/objects/objectsBase.rst.txt @@ -0,0 +1,6 @@ +=========== +objectsBase +=========== + +.. automodule:: robofab.objects.objectsBase + :members: diff --git a/_sources/api/objects/objectsFF.rst.txt b/_sources/api/objects/objectsFF.rst.txt new file mode 100644 index 0000000..dfa117d --- /dev/null +++ b/_sources/api/objects/objectsFF.rst.txt @@ -0,0 +1,6 @@ +========= +objectsFF +========= + +.. automodule:: robofab.objects.objectsFF + :members: diff --git a/_sources/api/objects/objectsFL.rst.txt b/_sources/api/objects/objectsFL.rst.txt new file mode 100644 index 0000000..019bceb --- /dev/null +++ b/_sources/api/objects/objectsFL.rst.txt @@ -0,0 +1,6 @@ +========= +objectsFL +========= + +.. automodule:: robofab.objects.objectsFL + :members: diff --git a/_sources/api/objects/objectsRF.rst.txt b/_sources/api/objects/objectsRF.rst.txt new file mode 100644 index 0000000..2293d07 --- /dev/null +++ b/_sources/api/objects/objectsRF.rst.txt @@ -0,0 +1,6 @@ +========= +objectsRF +========= + +.. automodule:: robofab.objects.objectsRF + :members: diff --git a/_sources/api/pens/adapterPens.rst.txt b/_sources/api/pens/adapterPens.rst.txt new file mode 100644 index 0000000..91b6700 --- /dev/null +++ b/_sources/api/pens/adapterPens.rst.txt @@ -0,0 +1,6 @@ +=========== +adapterPens +=========== + +.. automodule:: robofab.pens.adapterPens + :members: diff --git a/_sources/api/pens/angledMarginPen.rst.txt b/_sources/api/pens/angledMarginPen.rst.txt new file mode 100644 index 0000000..56a03dc --- /dev/null +++ b/_sources/api/pens/angledMarginPen.rst.txt @@ -0,0 +1,6 @@ +=============== +angledMarginPen +=============== + +.. automodule:: robofab.pens.angledMarginPen + :members: diff --git a/_sources/api/pens/boundsPen.rst.txt b/_sources/api/pens/boundsPen.rst.txt new file mode 100644 index 0000000..95494ec --- /dev/null +++ b/_sources/api/pens/boundsPen.rst.txt @@ -0,0 +1,6 @@ +========= +boundsPen +========= + +.. automodule:: robofab.pens.boundsPen + :members: diff --git a/_sources/api/pens/digestPen.rst.txt b/_sources/api/pens/digestPen.rst.txt new file mode 100644 index 0000000..d1c5f77 --- /dev/null +++ b/_sources/api/pens/digestPen.rst.txt @@ -0,0 +1,6 @@ +========= +digestPen +========= + +.. automodule:: robofab.pens.digestPen + :members: diff --git a/_sources/api/pens/filterPen.rst.txt b/_sources/api/pens/filterPen.rst.txt new file mode 100644 index 0000000..fa4a692 --- /dev/null +++ b/_sources/api/pens/filterPen.rst.txt @@ -0,0 +1,6 @@ +========= +filterPen +========= + +.. automodule:: robofab.pens.filterPen + :members: diff --git a/_sources/api/pens/flPen.rst.txt b/_sources/api/pens/flPen.rst.txt new file mode 100644 index 0000000..f453ccf --- /dev/null +++ b/_sources/api/pens/flPen.rst.txt @@ -0,0 +1,6 @@ +===== +flPen +===== + +.. automodule:: robofab.pens.flPen + :members: diff --git a/_sources/api/pens/marginPen.rst.txt b/_sources/api/pens/marginPen.rst.txt new file mode 100644 index 0000000..cc7be7a --- /dev/null +++ b/_sources/api/pens/marginPen.rst.txt @@ -0,0 +1,6 @@ +========= +marginPen +========= + +.. automodule:: robofab.pens.marginPen + :members: diff --git a/_sources/api/pens/mathPens.rst.txt b/_sources/api/pens/mathPens.rst.txt new file mode 100644 index 0000000..58337cd --- /dev/null +++ b/_sources/api/pens/mathPens.rst.txt @@ -0,0 +1,6 @@ +======== +mathPens +======== + +.. automodule:: robofab.pens.mathPens + :members: diff --git a/_sources/api/pens/pens.rst.txt b/_sources/api/pens/pens.rst.txt new file mode 100644 index 0000000..337cfe0 --- /dev/null +++ b/_sources/api/pens/pens.rst.txt @@ -0,0 +1,21 @@ +==== +pens +==== + +.. py:module:: robofab.pens + +.. toctree:: + :maxdepth: 1 + + adapterPens.rst + angledMarginPen.rst + boundsPen.rst + digestPen.rst + filterPen.rst + flPen.rst + marginPen.rst + mathPens.rst + pointPen.rst + quartzPen.rst + reverseContourPointPen.rst + rfUFOPen.rst diff --git a/_sources/api/pens/pointPen.rst.txt b/_sources/api/pens/pointPen.rst.txt new file mode 100644 index 0000000..7a11f9e --- /dev/null +++ b/_sources/api/pens/pointPen.rst.txt @@ -0,0 +1,6 @@ +======== +pointPen +======== + +.. automodule:: robofab.pens.pointPen + :members: diff --git a/_sources/api/pens/quartzPen.rst.txt b/_sources/api/pens/quartzPen.rst.txt new file mode 100644 index 0000000..8b7539b --- /dev/null +++ b/_sources/api/pens/quartzPen.rst.txt @@ -0,0 +1,6 @@ +========= +quartzPen +========= + +.. automodule:: robofab.pens.quartzPen + :members: diff --git a/_sources/api/pens/reverseContourPointPen.rst.txt b/_sources/api/pens/reverseContourPointPen.rst.txt new file mode 100644 index 0000000..e9b220c --- /dev/null +++ b/_sources/api/pens/reverseContourPointPen.rst.txt @@ -0,0 +1,6 @@ +====================== +reverseContourPointPen +====================== + +.. automodule:: robofab.pens.reverseContourPointPen + :members: diff --git a/_sources/api/pens/rfUFOPen.rst.txt b/_sources/api/pens/rfUFOPen.rst.txt new file mode 100644 index 0000000..2010dd5 --- /dev/null +++ b/_sources/api/pens/rfUFOPen.rst.txt @@ -0,0 +1,6 @@ +======== +rfUFOPen +======== + +.. automodule:: robofab.pens.rfUFOPen + :members: diff --git a/_sources/api/plistFromTree.rst.txt b/_sources/api/plistFromTree.rst.txt new file mode 100644 index 0000000..387eaa1 --- /dev/null +++ b/_sources/api/plistFromTree.rst.txt @@ -0,0 +1,6 @@ +============= +plistFromTree +============= + +.. automodule:: robofab.plistFromTree + :members: diff --git a/_sources/api/plistlib.rst.txt b/_sources/api/plistlib.rst.txt new file mode 100644 index 0000000..cb1fc29 --- /dev/null +++ b/_sources/api/plistlib.rst.txt @@ -0,0 +1,6 @@ +======== +plistlib +======== + +.. automodule:: robofab.plistlib + :members: diff --git a/_sources/api/test/test.rst.txt b/_sources/api/test/test.rst.txt new file mode 100644 index 0000000..22f6f87 --- /dev/null +++ b/_sources/api/test/test.rst.txt @@ -0,0 +1,21 @@ +==== +test +==== + +.. py:module:: robofab.test + +.. toctree:: + :maxdepth: 1 + + test_dialogs.rst + test_fontLabUFOReadWrite.rst + test_glifLib.rst + test_noneLabUFOReadWrite.rst + test_objectsFL.rst + test_objectsUFO.rst + test_pens.rst + test_psHints.rst + test_RInfoFL.rst + test_RInfoRF.rst + test_ufoLib.rst + testSupport.rst diff --git a/_sources/api/test/test_dialogs.rst.txt b/_sources/api/test/test_dialogs.rst.txt new file mode 100644 index 0000000..b3ec6d6 --- /dev/null +++ b/_sources/api/test/test_dialogs.rst.txt @@ -0,0 +1,6 @@ +============ +test_dialogs +============ + +.. automodule:: robofab.test.test_dialogs + :members: diff --git a/_sources/api/test/test_glifLib.rst.txt b/_sources/api/test/test_glifLib.rst.txt new file mode 100644 index 0000000..abaa9e7 --- /dev/null +++ b/_sources/api/test/test_glifLib.rst.txt @@ -0,0 +1,6 @@ +============ +test_glifLib +============ + +.. automodule:: robofab.test.test_glifLib + :members: diff --git a/_sources/api/test/test_noneLabUFOReadWrite.rst.txt b/_sources/api/test/test_noneLabUFOReadWrite.rst.txt new file mode 100644 index 0000000..0ffec80 --- /dev/null +++ b/_sources/api/test/test_noneLabUFOReadWrite.rst.txt @@ -0,0 +1,6 @@ +======================== +test_noneLabUFOReadWrite +======================== + +.. automodule:: robofab.test.test_noneLabUFOReadWrite + :members: diff --git a/_sources/api/test/test_objectsUFO.rst.txt b/_sources/api/test/test_objectsUFO.rst.txt new file mode 100644 index 0000000..6bdba43 --- /dev/null +++ b/_sources/api/test/test_objectsUFO.rst.txt @@ -0,0 +1,6 @@ +=============== +test_objectsUFO +=============== + +.. automodule:: robofab.test.test_objectsUFO + :members: diff --git a/_sources/api/test/test_pens.rst.txt b/_sources/api/test/test_pens.rst.txt new file mode 100644 index 0000000..c98f3cf --- /dev/null +++ b/_sources/api/test/test_pens.rst.txt @@ -0,0 +1,6 @@ +========= +test_pens +========= + +.. automodule:: robofab.test.test_pens + :members: diff --git a/_sources/api/test/test_psHints.rst.txt b/_sources/api/test/test_psHints.rst.txt new file mode 100644 index 0000000..6bb9139 --- /dev/null +++ b/_sources/api/test/test_psHints.rst.txt @@ -0,0 +1,6 @@ +============ +test_psHints +============ + +.. automodule:: robofab.test.test_psHints + :members: diff --git a/_sources/api/tools/accentBuilder.rst.txt b/_sources/api/tools/accentBuilder.rst.txt new file mode 100644 index 0000000..ccf6daf --- /dev/null +++ b/_sources/api/tools/accentBuilder.rst.txt @@ -0,0 +1,6 @@ +============= +accentBuilder +============= + +.. automodule:: robofab.tools.accentBuilder + :members: diff --git a/_sources/api/tools/fontlabFeatureSplitter.rst.txt b/_sources/api/tools/fontlabFeatureSplitter.rst.txt new file mode 100644 index 0000000..295abb2 --- /dev/null +++ b/_sources/api/tools/fontlabFeatureSplitter.rst.txt @@ -0,0 +1,6 @@ +====================== +fontlabFeatureSplitter +====================== + +.. automodule:: robofab.tools.fontlabFeatureSplitter + :members: diff --git a/_sources/api/tools/glifExport.rst.txt b/_sources/api/tools/glifExport.rst.txt new file mode 100644 index 0000000..067f5b3 --- /dev/null +++ b/_sources/api/tools/glifExport.rst.txt @@ -0,0 +1,6 @@ +======= +glifLib +======= + +.. automodule:: robofab.glifLib + :members: diff --git a/_sources/api/tools/glifImport.rst.txt b/_sources/api/tools/glifImport.rst.txt new file mode 100644 index 0000000..9b9efba --- /dev/null +++ b/_sources/api/tools/glifImport.rst.txt @@ -0,0 +1,6 @@ +========== +glifImport +========== + +.. automodule:: robofab.tools.glifImport + :members: diff --git a/_sources/api/tools/glyphConstruction.rst.txt b/_sources/api/tools/glyphConstruction.rst.txt new file mode 100644 index 0000000..c9aa0d0 --- /dev/null +++ b/_sources/api/tools/glyphConstruction.rst.txt @@ -0,0 +1,6 @@ +================= +glyphConstruction +================= + +.. automodule:: robofab.tools.glyphConstruction + :members: diff --git a/_sources/api/tools/glyphNameSchemes.rst.txt b/_sources/api/tools/glyphNameSchemes.rst.txt new file mode 100644 index 0000000..16cb1d8 --- /dev/null +++ b/_sources/api/tools/glyphNameSchemes.rst.txt @@ -0,0 +1,6 @@ +================ +glyphNameSchemes +================ + +.. automodule:: robofab.tools.glyphNameSchemes + :members: diff --git a/_sources/api/tools/index.rst.txt b/_sources/api/tools/index.rst.txt new file mode 100644 index 0000000..8f422f6 --- /dev/null +++ b/_sources/api/tools/index.rst.txt @@ -0,0 +1,24 @@ +===== +tools +===== + +.. automodule:: robofab.tools + :members: + +.. toctree:: + :maxdepth: 1 + + accentBuilder.rst + fontlabFeatureSplitter.rst + glifExport.rst + glifImport.rst + glyphConstruction.rst + glyphNameSchemes.rst + objectDumper.rst + otFeatures.rst + proof.rst + remote.rst + rfPrefs.rst + toolsAll.rst + toolsFL.rst + toolsRF.rst \ No newline at end of file diff --git a/_sources/api/tools/objectDumper.rst.txt b/_sources/api/tools/objectDumper.rst.txt new file mode 100644 index 0000000..c5087b1 --- /dev/null +++ b/_sources/api/tools/objectDumper.rst.txt @@ -0,0 +1,6 @@ +============ +objectDumper +============ + +.. automodule:: robofab.tools.objectDumper + :members: diff --git a/_sources/api/tools/otFeatures.rst.txt b/_sources/api/tools/otFeatures.rst.txt new file mode 100644 index 0000000..f893422 --- /dev/null +++ b/_sources/api/tools/otFeatures.rst.txt @@ -0,0 +1,6 @@ +========== +otFeatures +========== + +.. automodule:: robofab.tools.otFeatures + :members: diff --git a/_sources/api/tools/proof.rst.txt b/_sources/api/tools/proof.rst.txt new file mode 100644 index 0000000..4be8252 --- /dev/null +++ b/_sources/api/tools/proof.rst.txt @@ -0,0 +1,6 @@ +===== +proof +===== + +.. automodule:: robofab.tools.proof + :members: diff --git a/_sources/api/tools/remote.rst.txt b/_sources/api/tools/remote.rst.txt new file mode 100644 index 0000000..59ffc57 --- /dev/null +++ b/_sources/api/tools/remote.rst.txt @@ -0,0 +1,6 @@ +====== +remote +====== + +.. automodule:: robofab.tools.remote + :members: diff --git a/_sources/api/tools/rfPrefs.rst.txt b/_sources/api/tools/rfPrefs.rst.txt new file mode 100644 index 0000000..5f0264c --- /dev/null +++ b/_sources/api/tools/rfPrefs.rst.txt @@ -0,0 +1,6 @@ +======= +rfPrefs +======= + +.. automodule:: robofab.tools.rfPrefs + :members: diff --git a/_sources/api/tools/toolsAll.rst.txt b/_sources/api/tools/toolsAll.rst.txt new file mode 100644 index 0000000..eeea912 --- /dev/null +++ b/_sources/api/tools/toolsAll.rst.txt @@ -0,0 +1,6 @@ +======== +toolsAll +======== + +.. automodule:: robofab.tools.toolsAll + :members: diff --git a/_sources/api/tools/toolsFL.rst.txt b/_sources/api/tools/toolsFL.rst.txt new file mode 100644 index 0000000..f60c14c --- /dev/null +++ b/_sources/api/tools/toolsFL.rst.txt @@ -0,0 +1,6 @@ +======= +toolsFL +======= + +.. automodule:: robofab.tools.toolsFL + :members: diff --git a/_sources/api/tools/toolsRF.rst.txt b/_sources/api/tools/toolsRF.rst.txt new file mode 100644 index 0000000..9ebec29 --- /dev/null +++ b/_sources/api/tools/toolsRF.rst.txt @@ -0,0 +1,7 @@ +======= +toolsRF +======= + +.. automodule:: robofab.tools.toolsRF + :members: + diff --git a/_sources/api/ufoLib.rst.txt b/_sources/api/ufoLib.rst.txt new file mode 100644 index 0000000..3df89b0 --- /dev/null +++ b/_sources/api/ufoLib.rst.txt @@ -0,0 +1,6 @@ +====== +ufoLib +====== + +.. automodule:: robofab.ufoLib + :members: diff --git a/_sources/api/world.rst.txt b/_sources/api/world.rst.txt new file mode 100644 index 0000000..6b3ed9f --- /dev/null +++ b/_sources/api/world.rst.txt @@ -0,0 +1,6 @@ +===== +world +===== + +.. automodule:: robofab.world + :members: diff --git a/_sources/api/xmlTreeBuilder.rst.txt b/_sources/api/xmlTreeBuilder.rst.txt new file mode 100644 index 0000000..e362910 --- /dev/null +++ b/_sources/api/xmlTreeBuilder.rst.txt @@ -0,0 +1,6 @@ +============== +xmlTreeBuilder +============== + +.. automodule:: robofab.xmlTreeBuilder + :members: diff --git a/_sources/howtos/building_accents.rst.txt b/_sources/howtos/building_accents.rst.txt new file mode 100644 index 0000000..492b009 --- /dev/null +++ b/_sources/howtos/building_accents.rst.txt @@ -0,0 +1,72 @@ +Building accents +================ + +Making accented glyphs is a job where scripting can help save some time. When you have prepared all the parts, the base glyphs and the accents, a script can help to assemble the combinations. There are various ways of doing it, let's start with a simple one: + +.. showcode:: ../../examples/howtos/buildingAccents_00.py + +In this example the script creates a new glyph, ``aacute``, then proceeds to add components, references to other glyphs rather than the glyphs themselves. The glyph method ``appendComponent`` is used to do this. See how the acute component has an extra argument, ``(200, 0)`` -- this the offset for the accent. Finally the new glyph is given the width of the base ``a``. + +This example illustrates the use of the very basic ``appendComponent`` method. But it's not a very useful way to make glyphs. For instance, the string ``aacute`` could easily be made into a variable taken from a list. And dealing with the offsets when placing the accent isn't going to be efficient either when you want to make a large list of accented glyphs. How to go about it that? + +Building accents automagically +------------------------------ + +RoboFab has its own database which connects glyphnames to components. In the RoboFab distribution folder, go to ``Data/GlyphConstruction.txt``. This text file contains a list of glyphnames and from which components they should be built. The RoboFab Glyph Construction database was based on FontLab's glyph list. This list contains information about where components should be connected:: + + Acircumflexdotaccent: A circumflex.top dotaccent.bottom + +This entry shows that ``Acircumflexdotaccent`` is constructed with components from ``A``, a ``circumflex`` using the ``top`` anchor, and ``dotaccent`` using the ``bottom`` anchor. + +Generate a glyph +---------------- + +RoboFab's Font object has several ways of starting component glyphs and adding stuff to them. There are different strategies possible for different kinds of problems. + +font.generateGlyph(glyphName, replace, preflight, printErrors) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The easiest method to add an assembled glyph to a font is using the font's ``generateGlyph`` method. This will look for the glyphname in the glyph construction database and attempt to get all the components and place them at the anchors listed in the database. Let's have a look at its parameters: + +**glyphName** + The name of the glyph, has to correspond to a name in the glyph construction database. + +**replace** + Default set to ``True``, the new glyph will replace the old one if it exists. + +**preflight** + Default set to ``False``, preflight gives you the opportunity to run the glyph creation process without actually adding it to the font. This is useful if you're building the characterset and you don't have all the parts yet. Preflight will return a list of missing anchor points, missing accents, components, etc. Note that it can take several iterations of fixing problems and discovering new ones. If for instance a glyph for a component can't be found, it also means that some problems with that glyph are hidden. i.e. when a glyph ``A`` can't be found, preflight can't tell you that this glyph is missing a required anchor point either. + +**printErrors** + Default set to ``True``, print any errors and problems to the standard output window. + +font.compileGlyph(glyphName, baseName, accentNames, adjustWidth=False, preflight=False, printErrors=True) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Compile a glyph with specified components. If you want to assemble accents that are not the glyph construction database, using compileGlyph. + +**glyphName** + the name of the glyph where it all needs to go. + +**baseName** + the name of the base glyph. ``accentNames``: a list of ``accentName``, ``anchorName`` tuples: ``[('acute', 'top'), etc]`` + +**preflight** + default set to ``False``, preflight gives you the opportunity to run the glyph creation process without actually adding it to the font. This is useful if you're building the characterset and you don't have all the parts yet. Preflight will return a list of missing anchor points, missing accents, components, etc. + +**printErrors** + default set to ``True``, print any errors and problems to the standard output window. + +AccentBuilder +------------- + +RoboFab comes with a versatile accent building tool, ``AccentBuilder``. Have a look at :py:mod:`robofab.tools.accentbuilder`. ``AccentBuilder`` deals with components, anchorpoints: + +.. showcode:: ../../examples/howtos/buildingAccents_01.py + +Building your own accentbuilders +-------------------------------- + +For typeface production it is a good idea to build a set of standardised tools with which you finalise the font data. Here's an example of a script which adds a standardised list of accents to a font. It does not do automatic anchor placement because the scripter wanted to do this manually. But the rest is done automatically. The script also deals correctly with smallcap glyphnames with ``.sc``: + +.. showcode:: ../../examples/howtos/buildingAccents_02.py diff --git a/_sources/howtos/fontlab_remote.rst.txt b/_sources/howtos/fontlab_remote.rst.txt new file mode 100644 index 0000000..8da5fe6 --- /dev/null +++ b/_sources/howtos/fontlab_remote.rst.txt @@ -0,0 +1,75 @@ +FontLab Remote +============== + +A neat feature in RoboFab for FontLab on MacOS. RoboFab can install an AppleEvent handler in FontLab to make FontLab respond to calls from other applications. There is code to communicate with FontLab using this AppleEvent and to make it execute code and exchange data such as glyphs. How useful this remote stuff is depends on what you want to do with it. We thought it was cool. The 'remote' relates to one application controlling another. Both applications need to run on the same machine, it does not mean that FontLab is accepting commands over a network for instance. For that we need another tool. + +How? +---- + +Step 1: Start the remote stuff in FontLab +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The first thing you need to do is start the AppleEvent support in FontLab. That's done by importing the remote module: + +.. showcode:: ../../examples/howtos/fontlabRemote_00.py + +.. code:: + + FontLabRemote is on. + +Step 2: Start the Python IDE +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +You can now send commands, bits of code and entire glyphs to FontLab from the Python IDE: + +.. showcode:: ../../examples/howtos/fontlabRemote_01.py + +.. code:: + + 2 + +The function ``runFontLabRemote()`` sends a piece of Python code to FontLab's python interpreter and has it executed. In this example the code is ``print 1+1``. The result, the output of FontLab running this piece of code is then returned to the Python IDE. Note that the output is always a string. Depending on the code you throw at FontLab it could even contain tracebacks or other output. + +When FontLab receives and executes a remote command, it will print a note to the FontLab Output window:: + + < executing remote command > + < executing remote command > + < executing remote command > + +That means that FontLab is doing remote stuff. + +Step 3: Teleporting a Glyph +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The remote module has support to send and receive Glyphs. For the next example open a new font in FontLab first (command N), then run the following code in the Python IDE. Make sure you have a UFO font handy somewhere: + +.. showcode:: ../../examples/howtos/fontlabRemote_02.py + +If all went well, you now have the ``n`` from your UFO copied to the right slot in your FontLab font. As noted earlier, if all you want to do is import some glyphs from a UFO into FontLab there is absolutely no need to use all this remote stuff. + +Why? +---- + +The remote module only takes care of the communication with FontLab. Possible applications which could be built on top of this are: + +- Use FontLab to perform outline operations such as remove overlap. +- Use FontLab to batch process font generation. +- Build an external editor to augment the functionality of FontLab. + +As noted before, the remote stuff only works on MacOS. + +Example +^^^^^^^ + +Example in which a glyph from a UFO opened in plain Python is copied to FontLab. After removing overlap the glyph is returned and inserted in the UFO: + +.. showcode:: ../../examples/howtos/fontlabRemote_03.py + +Possible results:: + + Number of contours before: 6 + Number of contours after: 4 + +.. note:: + + While experimenting with ``robofab.tools.remote`` we found that after some time it's possible that FontLab grows weary of the remote fussing and the scripts stop working. Restarting FontLab usually solves that situation. diff --git a/_sources/howtos/generating_fonts.rst.txt b/_sources/howtos/generating_fonts.rst.txt new file mode 100644 index 0000000..e481374 --- /dev/null +++ b/_sources/howtos/generating_fonts.rst.txt @@ -0,0 +1,54 @@ +Generating Fonts +================ + +A ``RFont`` object in FontLab can call FontLab to generate fonts. Generating fonts can be time consuming, even when all the right parameters are set. So this is a nice candidate for automation. First of all a generator script will give you consistency between generations and versions. But also it means you can set a machine to work to generate batches of fonts and focus on more creative tasks. + +.. note:: + + The generate method only calls on FontLab to generate the fonts in a particular format. It does not prepare the font data for that specific format, i.e. for example when you're generating for PC Truetype, ``generate()`` won't select the appropriate encodings or special windows flags. You need to do that. + +RFont.generate(outputType, path=None) +------------------------------------- + +Generate the font. ``outputType`` is the type of font to output. An overview of available output types in FontLab: + ++---------------+----------------------------------------------------------------------+ +| output type | description | ++===============+======================================================================+ +| pctype1 | PC Type 1 font (binary/PFB) | ++---------------+----------------------------------------------------------------------+ +| pcmm | PC MultipleMaster font (PFB). | ++---------------+----------------------------------------------------------------------+ +| pctype1ascii | PC Type 1 font (ASCII/PFA). | ++---------------+----------------------------------------------------------------------+ +| pcmmascii | PC MultipleMaster font (ASCII/PFA). | ++---------------+----------------------------------------------------------------------+ +| mactype1 | Mac Type 1 font (generates suitcase and LWFN file). | ++---------------+----------------------------------------------------------------------+ +| otfcff | PS OpenType (CFF-based) font (OTF). | ++---------------+----------------------------------------------------------------------+ +| otfttf | PC TrueType/TT OpenType font (TTF). | ++---------------+----------------------------------------------------------------------+ +| macttf | Mac TrueType font (generates suitcase). | ++---------------+----------------------------------------------------------------------+ +| macttdfont | Mac TrueType font (generates suitcase with resources in data fork). | ++---------------+----------------------------------------------------------------------+ + +Docs adapted from the `Unofficial FontLab/Python API Reference `_. + +.. note:: + + The value of ``path`` can be a directory or a directory file name combo: + + - ``path="DirectoryA/DirectoryB"`` + - ``path="DirectoryA/DirectoryB/MyFontName"`` + - ``path="DirectoryA/DirectoryB/"`` + + If no ``path`` is given, the file will be output in the same directory as the ``.vfb`` file. If no file name is given, the generated file name will be the same as the ``.vfb`` file, with the appropriate suffix. + +Examples +-------- + +FontLab can generate many different formats for different platforms. Please refer to the FontLab manual for specifics. Some formats generate several files, others only one. Some formats are not available in all versions of FontLab: + +.. showcode:: ../../examples/howtos/generatingFonts_00.py diff --git a/_sources/howtos/glifnames.rst.txt b/_sources/howtos/glifnames.rst.txt new file mode 100644 index 0000000..cd46841 --- /dev/null +++ b/_sources/howtos/glifnames.rst.txt @@ -0,0 +1,32 @@ +Glyphnames versus GLIF-names +============================ + +The names of the GLIF xml files, in the UFO are related to the glyph names. It used to be a 1:1 relationship, but then glyphnames grew really long and some file systems don't support long filenames. So something had to give. + +GlyphNamingSchemes +------------------ + +The ``objectsFL.RFont.writeUFO()`` method can take a special callback function in order to convert the actual glyphname to a suitable filename. The goal is to create unique filenames so that glyphs won't overwrite each other's exports, also comply to certain filesystems which require filenames to be shorter than a certain number of characters, while retaining a high level of human-readability. Have a look at ``robofab/tools/glyphNameSchemes.py`` for the currently available callbacks. With ``glyphNameSchemes``, the ``glyphName`` and the ``.glif`` filename no longer have a direct relationship. + +glyphNameToShortFileName(glyphName, glyphSet) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Features a guaranteed maximum filename (default 31 characters) for really long glyphnames, and clash testing. + +- All non-ascii characters are converted to ``_`` (underscore), including ``.`` (period). +- All glyphnames which are too long are truncated and a hash is added at the end. +- The hash is generated from the whole glyphname. +- Finally, the candidate glyphname is checked against the ``contents.plist`` and a incrementing number is added at the end if there is a glyph with that name already. + +``glyphNameToShortFileName`` is the **default naming scheme** for exporting UFOs from FontLab. For most everyday use, this callback does all the work and there is no need to tweak it. Below are some examples to give you an idea of what the callback does: + +.. showcode:: ../../examples/howtos/glifNames_00.py + +.. code:: + + "accent.glif" + "A_ccent.glif" + "this_is_a_very_lon340a8fa5.glif" + "a_alt.glif" + "_notdef.glif" + "_nic_de.glif" diff --git a/_sources/howtos/glyphmath.rst.txt b/_sources/howtos/glyphmath.rst.txt new file mode 100644 index 0000000..cac0651 --- /dev/null +++ b/_sources/howtos/glyphmath.rst.txt @@ -0,0 +1,96 @@ +Glyph Math +========== + +``RGlyph`` objects have methods that allow the objects to behave a bit like variables in simple math. These methods do not do additions or substractions of the surface area of the glyphs, like layering two glyphs on top of each other and than doing "remove overlap". Instead, they return new glyph objects in which each coordinate in each contour is the product of the two glyphs. + +Objects +------- + +All glyph math operations in have new, orphaned, objects as result. For instance a substraction of two FontLab RoboFab glyphs will result in a new glyph object, but it won't be part of the font. If you want the result to be part of the font you have to add it explicitly, see the example at the bottom of this page. There are several reasons for this: + +- The result might not even come from glyphs in the same font, i.e. you can substract a glyph in one font from a glyph in another font. Where should the result live? You decide. + +- You might not want the result to be part of your font when you're using it for further calculations. So: results from glyphmath operations are orphan glyphs that do not belong to any font. + +- The results need to use floating point (``19.234943``) numbers for precision, FontLab only stores integer numbers (``19``). + +If you want to add a glyph (of any flavor, FontLab or UFO) to a font use the appendGlyph method:: + + someNewGlyph = aFont.newGlyph("someNewGlyph") + someNewGlyph.appendGlyph(restultFromGlyphMath) + + # note you have to set the width, + # appendGlyph does not automatically take the value. + someNewGlyph.width = restultFromGlyphMath.width + +Subtraction +----------- + +Substraction returns a new glyph object with contours which represent the **difference** between the two previous glyphs. As a glyph itself, it's not much to look at. If you draw the result of a substraction it will probably look like a crumpled outline. + +Example Subtraction +^^^^^^^^^^^^^^^^^^^ + +.. code:: + + f = CurrentFont() + g = f["a"] + h = f["b"] + # suppose g and h have compatible point structures + myRelativeGlyph = g - h + +Addition +-------- + +Addition returns a new glyph object with the contours which is the product of the two previous glyphs. If you just add two "normal" glyphs from a font (or multiple fonts for that matter) it will look odd. But you can also easily add a relative glyph (a result of substracting one glyph from another), which effectively means you're applying the difference between two glyphs to a third. And that can be a very useful action. + +Example Addition +^^^^^^^^^^^^^^^^ + +.. code:: + + # continue with myRelativeGlyph from the previous example + newglyph = f["x"] + myRelativeGlyph + +Multiplication +-------------- + +When a normal glyph is multiplied it looks as if the glyph has been scaled. For instance multiplying a glyph with ``0.5`` scales the shapes 50%. + +Example Multiplication +^^^^^^^^^^^^^^^^^^^^^^ + +.. code:: + + # continue with myRelativeGlyph from the previous example + newglyph = f["x"] + 0.25 * myRelativeGlyph + +Division +-------- + +Divisions works just like multiplications, you just need to make sure not to divide by zero. + +Example Division +^^^^^^^^^^^^^^^^ + +.. code:: + + # continue with myRelativeGlyph from the previous example + newglyph = f["x"] + myRelativeGlyph / 4 + +Combinations +------------ + +These examples are simple enough, but when you combine them the operations can become really powerful. You could recreate font interpolation using GlyphMath, or construct new networks of interpolations, additions, shifts, deltas that were impossible to build. + +All together now +^^^^^^^^^^^^^^^^ + +This is from the ``demo_GlyphMath.py`` which should be in the ``Scripts/RoboFabIntro`` folder: + +.. showcode:: ../../examples/howtos/glyphMath_00.py + +Implementation limits +--------------------- + +In ``objectsFL`` (for use in FontLab), only ``RGlyph`` has glyphmath operators implemented. The result of a glyphmath operation in FontLab is **always** an object from ``objectsRF``. In ``ObjectsRF`` most objects have ``*``, ``+`` and ``-`` implemented. But considering the operators are mainly used for Glyph stuff, the ``RGlyph`` object is a bit more kitted out with division as well. diff --git a/_sources/howtos/index.rst.txt b/_sources/howtos/index.rst.txt new file mode 100644 index 0000000..b4628dd --- /dev/null +++ b/_sources/howtos/index.rst.txt @@ -0,0 +1,40 @@ +How To's +======== + +.. toctree:: + :maxdepth: 1 + :hidden: + + ot_features.rst + building_accents.rst + fontlab_remote.rst + generating_fonts.rst + glifnames.rst + lowlevel.rst + interpolate.rst + makeufo.rst + scripting.rst + world.rst + understanding_contours.rst + glyphmath.rst + use_pens.rst + use_lib.rst + use_transformations.rst + +This section provides some cases on how to use the RoboFab objects in everyday type design work. + +- :doc:`OpenType Features in UFO `: How to import, export and work with features in UFO. +- :doc:`Building accents `: Use RoboFab to build accented glyphs with components. +- :doc:`FontLab Remote `: Use AppleEvents to control FontLab in Mac OSX +- :doc:`Generate Fonts `: How to generate fonts with RoboFab in FontLab. +- :doc:`Glyphnames versus GLIF-names `: How to use Robofab's glyph naming schemes for UFO export. +- :doc:`How to get to FontLab stuff `: The naked methods and attributes. +- :doc:`How to interpolate `: How to do interpolation with RoboFab objects. +- :doc:`How to make a UFO `: Export and import UFO's in FontLab +- :doc:`Scripting `: Simple examples. +- :doc:`The world module `: What on earth is it for? +- :doc:`Understanding Contours `: How contours, segments and points work. +- :doc:`Using Glyph Math `: Applying math operators on glyph objects. +- :doc:`Using Pens `: Playing with pen objects. +- :doc:`Using the lib `: Make the ``glyph.lib`` and ``font.lib`` work for you. +- :doc:`Using transformations `: Matrix transformations in RoboFab. diff --git a/_sources/howtos/interpolate.rst.txt b/_sources/howtos/interpolate.rst.txt new file mode 100644 index 0000000..d5189e5 --- /dev/null +++ b/_sources/howtos/interpolate.rst.txt @@ -0,0 +1,73 @@ +How to interpolate +================== + +RoboFab's interpolation is independent of the interpolation tools provided in FontLab. First of all that means that you can interpolate UFO fonts without the help of FontLab. It also means that the interpolation engine works different than the one in FontLab. + +Strict +------ + +RoboFab interpolation is very strict. It won't interpolate unless the point structures of both extremes match. It won't mess with the masters, force points or anything. The user has to get it right. + +aGlyph.isCompatible(otherGlyph, report=True) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Glyph has a method ``isCompatible()`` which reports whether or not the point structures are capable of interpolating. With this method you can run through your proposed interpolation first and see if all glyphs work, and perhaps send feedback to the user: + +.. showcode:: ../../examples/howtos/interpolate_00.py + +.. code:: + + False + +``isCompatible`` has a flag report which if set to ``True`` will return a tuple with a report on the incompatibilities: + +.. showcode:: ../../examples/howtos/interpolate_01.py + +.. code:: + + (False, ["Fatal error: contour 0 in glyph a and + glyph b don't have the same number of segments."]) + +aFont.interpolate(factor, minFont, maxFont, suppressError=True, analyzeOnly=False) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Interpolate by factor between ``minFont`` and ``maxFont``. In FontLab the result of the interpolation will be rounded to whole integers. In NoneLab (outside FontLab, operating on a UFO), the result of the interpolation is a font with glyphs with floating point coordinates so if you want to use the result of one interpolation as a master in the next you won't loose precision to rounding errors. It might mean that for some uses of UFO you need to round the glyphs afterwards. ``aFont.interpolate`` also interpolates the positions of components, anchors, ascender, descender, and glyph widths for the whole font. + +**factor** + Either a number or a tuple of numbers. Usually factor is a float number between ``0`` and ``1``. ``0`` produces ``minGlyph``, ``1`` produces ``maxGlyph``. Values ``>`` extrapolate beyond ``maxGlyph``. Values ``<`` extrapolate beyond ``minGlyph``. If you pass ``(x, y)`` to ``factor`` it will interpolate horizontal values differently from vertical values. For instance ``(0, 1)`` as factor produces a font (or a glyph) which horizontally looks like the minimum, but vertically it looks like the maximum. + +**minFont** + ``RFont`` object, the font for the minimum master. + +**maxFont** + ``RFont`` object, the font for the maximum master. + +**suppressError** (optional) + Will supress all tracebacks it finds on the way. That means that interpolation problems in individual glyphs won't stop the rest of the font from getting done. Default set to ``True``. + +**analyzeOnly** (optional) + Will do a dry run of the interpolation and do a full analysis of the compatibility and problems. It won't produce any outlines in the font. Default set to ``False``. + +:doc:`Kerning objects <../objects/RKerning>` have an interpolation method as well. It is debateable whether an interpolation of two fonts should also automatically interpolate the kerning, so we picked the more explicit approach: in your interpolation script you have to do the interpolation of the kerning objects seperately. + +Examples +-------- + +Straight interpolating (either FontLab or UFO) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Setting a third font to an interpolation of two others: + +.. showcode:: ../../examples/howtos/interpolate_02.py + +Interpolating two glyphs in the same font +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For any number of reasons you might want to interpolate a glyph within the same font. Here's how to do it:: + + >>> File cannot be tokenized by tokenize + +Alternatives +^^^^^^^^^^^^ + +These are the conventional ways of doing interpolation. Have a look at :doc:`RoboFab's GlyphMath ` for alternatives for blending and interpolating glyphs together. diff --git a/_sources/howtos/lowlevel.rst.txt b/_sources/howtos/lowlevel.rst.txt new file mode 100644 index 0000000..6eaedb1 --- /dev/null +++ b/_sources/howtos/lowlevel.rst.txt @@ -0,0 +1,16 @@ +How to get to FontLab's internals +================================= + +If you're using RoboFab in FontLab, it can happen that you need to access a method or attribute of a glyph or font object which does not seem to have an equivalent in RoboFab. What to do? + +Get Naked +--------- + +RoboFab ``Glyph`` and ``Font`` objects have a special method, ``naked()`` which returns the actual, low level FontLab object. This object can then be used with the documented FontLab methods and attributes. The methods and attributes of these FontLab objects are very different from RoboFab: + +.. showcode:: ../../examples/howtos/lowLevel_00.py + +.. code:: + + < RFont font for TemplatefontPro Rg Regular > + < Font 'TemplatefontPro Rg Regular' > diff --git a/_sources/howtos/makeufo.rst.txt b/_sources/howtos/makeufo.rst.txt new file mode 100644 index 0000000..241d03f --- /dev/null +++ b/_sources/howtos/makeufo.rst.txt @@ -0,0 +1,44 @@ +How to make a UFO +================= + +Exporting a FontLab font to UFO is easy: + +1. Open the ``.vfb``. +2. Select the *RoboFabUFO* menu in the Macro toolbar. +3. Select the *Export Current Font to UFO Format* script. +4. Run it. + +The ``.ufo`` will be in the same directory as the original ``.vfb`` file. Have an in-depth look at the :doc:`ufo format here <../intro/ufo>`. + +.. note:: If you want to export a new FontLab font to UFO, **it is important that you save the font to .vfb first**. + +Importing a UFO into FontLab +---------------------------- + +1. Select the *RoboFabUFO* menu in the Macro toolbar. +2. Select the *Import .ufo File into FontLab* script. +3. Run it. + +This script create a new, empty FontLab font, then proceed to ask you for a ``.ufo`` directory. + +.. note:: Due to some limitations in how FontLab keeps track of new, untitled, unsaved fonts, it is vital to **make sure that there are no other unsaved, untitled fonts open** when you run this script. Because if there are, FontLab will be confused about where to import the glyphs from the ``.ufo`` and none of the fonts will show the new glyphs. It's ok to have other fonts open when importing ``.ufo``, they just to have been saved previously. + +Importing a bunch of UFO's into FontLab +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +What if you need to import a whole family of UFO's? + +1. Select the *RoboFabUFO* menu in the Macro toolbar. +2. Select the *Import all UFOs in a folder* script. +3. Run it. + +This script will prompt you for a folder with UFO's. Pick one. The script will proceed to import the UFO's one by one. + +.. note:: Sometimes, some versions of FontLab can get a bit tired of importing UFO's in a batch. When this happens not all UFO's will be imported and FontLab may crash. When this happens, just import the fonts one by one. + +Making a UFO from a font binary +------------------------------- + +Using ``fontTools`` you can make a UFO directly from a font binary. This is very fast, and it works outside of FontLab, but not all data (for instance kerning and apparently metrics) is imported. So your mileage may vary: + +.. showcode:: ../../examples/howtos/makeUFO_00.py diff --git a/_sources/howtos/ot_features.rst.txt b/_sources/howtos/ot_features.rst.txt new file mode 100644 index 0000000..a06e10b --- /dev/null +++ b/_sources/howtos/ot_features.rst.txt @@ -0,0 +1,47 @@ +OpenType features in UFO +======================== + +The UFO specification does not have an explicit place or format for OpenType features. This has lead to some misunderstanding that it is not possible to work with OpenType features in UFO. This is not the case. Feature data can be stored in the ufo and manipulated. For instance, FontLab exports and imports feature data to and from UFO, storing the data in the ``font.lib`` (``font.ufo/lib.plist``) at ``com.robofab.features``. This page describes how the data is currently managed. It's likely this will improve in the future. + +Features +-------- + +Feature data in UFO is stored in ``font.lib['com.robofab.features']``. This is a dictionary with the four-letter feature tag as key and the feature text as value. As of RoboFab version 1.1.2, the order of the features is stored in ``font.lib['com.robofab.featureorder']``. Older UFO's without this entry will get their features imported in alphabetical order. OpenType classes are stored in ``font.groups`` (``ufo/groups.plist``): + +.. showcode:: ../../examples/howtos/otFeatures_00.py + +.. code:: + + ["com.robofab.features"] + ['ss01', 'liga', 'dlig'] + "feature liga { + sub f f i by ffi; + sub f f l by ffl; + } liga;" + ['liga', 'dlig', 'ss01'] + +Note that the feature data in the lib is used for storage in UFO. This data won't be available in robofab font objects in FontLab, where it makes more sense to address the FL objects directly. `Check the FL docs here `_. + +.. showcode:: ../../examples/howtos/otFeatures_01.py + +.. code:: + + [, + ] + +Kerning data +------------ + +Kerning is stored in ``font.kerning``, an object which behaves like a dictionary. A ``(name, name)`` tuple is the key. This can either be a glyph name or a group name. A number is the value. Can be floating point or integer: + +.. showcode:: ../../examples/howtos/kerning_00.py + +.. code:: + + [('a', 'v'), ('MMK_L_baseserif', 'n')] + -100 + +Why no RoboFab objects for features? +------------------------------------ + +Features are tricky things. On one level they're stored as simple pieces of text. On another level they're sets of complex rules which need to be executed. When the RoboFab API and UFO spec started, writing an interpreter for feature language was too far off. So we chose for a loose method of storing the data, just bits of text, which would get the data where it needed to go and back again. And leave the interpreting and executing to other applications. diff --git a/_sources/howtos/scripting.rst.txt b/_sources/howtos/scripting.rst.txt new file mode 100644 index 0000000..9ae4b94 --- /dev/null +++ b/_sources/howtos/scripting.rst.txt @@ -0,0 +1,108 @@ +Scripting +========= + +Scripting with RoboFab is programming in Python. Everything is possible, it's just that some things are easier than others. + +For Python Newbies +------------------ + +If you don't have much programming experience, or you're not familiar with Python, have a look at Just van Rossum's Drawbot_ (if you're on OSX that is). Drawbot is a low threshold app to play with python code and get awarded with nice eye candy. Learn the princples of programming, loops, variables, by building with graphic shapes, paths, colors. + +.. _Drawbot : http://drawbot.com/ + +RoboFab uses objects to address the various things you find in a font. Objects are a useful way to think about code. A font is an **object**. It has some **attributes**, values that belong to that object. A font object is also capable of doing stuff by calling its **methods**. None of this is specific to RoboFab, a lot of programming languages use objects, and Python does as well. Objects can contain other objects. Have a look at the :doc:`RoboFab object model <../objects/model>` to see how they are structured and what other objects there are besides Font. + +Other resources +^^^^^^^^^^^^^^^ + +This is an interesting introduction into programming with Python as well: `How to think like a computer scientist`_. A full introduction into programming goes beyond the scope of this manual. Then there are tons of books, websites, stuff. Do some googling. + +.. _How to think like a computer scientist : http://openbookproject.net/thinkcs/python/english2e/ + +For RoboFog Converts +-------------------- + +For those of you joining us from the cohorts of RoboFog users, here some some of the main points of difference. Maybe others will find this part interesting too. + +Packages and modules +^^^^^^^^^^^^^^^^^^^^ + +Robofab is set up with packages. This is to organise the large volume of code into smaller, easier to manage modules. RoboFab does not have any builtins anymore, so you have to import the stuff you want to work with. Look at :doc:`the use of the world module ` which is where a lot of stuff is made available for you. + +CurrentFont(), CurrentGlyph() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +We've kept the ``CurrentFont`` function to provide a font object for the front most font. And we've renamed ``CurrentChar`` into ``CurrentGlyph`` as RoboFab is fully unicode aware and we're dealing with glyphs, not characters. ``CurrentGlyph()`` returns a glyph object for the front most glyph. + +Segments, bPoints +^^^^^^^^^^^^^^^^^ + +Fonts store :doc:`glyphs <../objects/RGlyph>`, glyphs store :doc:`contours <../objects/RContour>`, just like RoboFog. Contours however have a few more tricks than their RoboFog counterparts. Contours have :doc:`segments <../objects/RSegment>`, a kind of cluster of a series of offcurve points and one on curve point (see :doc:`Understanding contours `). Contours also have lists of :doc:`points <../objects/RPoint>` and :doc:`bpoints <../objects/bPoint>`. Depending on what you need to do you can iterate through the segments or points or bpoints. + +Conversion, drawing +^^^^^^^^^^^^^^^^^^^ + +For scripts which convert or transform outline data in some way, consider writing a :doc:`Pen ` object for that conversion. These are also handy for drawing in glyphs. + +Where to start +-------------- + +You've seen that a lot of the examples in this manual start by importing some objects or functions from ``robofab.world``. This is an easy way to get to a font, and through the font you can get access to the glyphs and all other values that are associated with them. + +Open a font from any file +^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. showcode:: ../../examples/howtos/scripting_00.py + +.. code:: + + None # or a font object, depending on what you select + +Open a font from a specific file +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. showcode:: ../../examples/howtos/scripting_01.py + +.. code:: + + # a font object + +Do something with the font that's open +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. showcode:: ../../examples/howtos/scripting_02.py + +.. code:: + + # a font object for the font that's on top. + +How to proceed? +--------------- + +Programming is for a large part the art of picking one seemingly single problem apart and make a lot of smaller, solveable problems from it. Some random thoughts on the subject: + +First think about where to start: +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Does your problem have something to do with the entire font? +- Or the metrics? The widths? Sidebearings? Kerning? +- Or one single glyph? Or perhaps a group of glyph while excluding others? +- Do you need to move stuff around? +- Do you need to create new glyphs? + +Can you describe each step of the process +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- RoboFab can't be instructed to make judgements on aesthetics. +- You have to formulate small steps, first do this, then compare that. +- Use approaches and tricks you learned before to get ahead. +- Start with the simplest possible loop and test. +- Play around -- pick and object and try to make it do tricks. Use this documentation to see what methods and attributes each one has. + +Be patient +^^^^^^^^^^ + +- Programming and scripting is a skill just like any other. +- Eventhough some folks pick it up faster, anyone clever enough to understand typedesign can learn scripting. +- Read the documentation, try the examples, try the demos. Are there scripts that do something like what you want to do? Pick them apart, see how they work. Learn from the source. +- If you think that scripting is nothing like design consider this: it's certainly a nicer intellectual challenge to try to write some code, then it is to manually do repetitive, stupid production things for hours or days on end. Make the computers work for you, instead of the other way round. Scripting is control. diff --git a/_sources/howtos/understanding_contours.rst.txt b/_sources/howtos/understanding_contours.rst.txt new file mode 100644 index 0000000..3da8596 --- /dev/null +++ b/_sources/howtos/understanding_contours.rst.txt @@ -0,0 +1,100 @@ +Understanding Contours and Segments +=================================== + +Now, this is an important part of RoboFab so pay attention. In the world of digital font formats we have several different kinds of ways of describing outlines. Bezier curves for PostScript fonts, Quadratic curves for TrueType fonts. Each with their own peculiarities. RoboFab is format agnostic so it should be able to store all PostScript and all TrueType points. The structure here is meant to be able to do all that. + +Diagrams by Tal Leming. + +Contours +-------- + +A glyph can contain one or more contours. Depending on what you want to do, there are different ways of looking at the data of the contour, the points, the line segments. The ``RContour`` object is way to the outlines. + +.. figure:: ../../images/contours.jpg + :width: 300 px + :align: center + + a contour + +.. showcode:: ../../examples/howtos/understandingContours_00.py + +.. code:: + + < RContour for Mailer-Regular.a[0] > + 15 + # 15? 15 of what? + +.. seealso:: + + A description of the :doc:`RContour <../objects/RContour>` object. + +Segments +-------- + +This circle consists of a couple of segments, each a piece of of the contour. A contour is a sequence of segments, you can iterate through a contour to get segments. A contour also has methods for adding and deleting segments. + +.. figure:: ../../images/contours_segments.jpg + :width: 300 px + :align: center + + a contour's segments + +.. code:: + + # segment code example + +In turn, a segment is made up of a sequence of points. Any number of off-curve points followed by an on-curve point. For the PostScript-centric designers: in TrueType outlines it is allowed to have any number of off-curve points before an on-curve. These points know whether they need to be rendered as bezier of quadratic curves. + +.. figure:: ../../images/contours_segments_points.jpg + :width: 300 px + :align: center + + segments with on-curve and off-curve points + +.. seealso:: + + A description of the :doc:`RSegment <../objects/RSegment>` object. + +Points +------ + +Another way to look at a contour is as a sequence of on-curve and off-curve points. This is the approach taken by ``glyph.drawPoints()`` and ``PointPen``. + +.. figure:: ../../images/contours_points.jpg + :width: 300 px + :align: center + + points (on-curve and off-curve) + +.. showcode:: ../../examples/howtos/understandingContours_02.py + +.. code:: + + < RPoint for Special-Bold.A[0][0] > + < RPoint for Special-Bold[1][1] > + etc.. + +.. seealso:: A description of the :doc:`RPoint <../objects/RPoint>` object. + +bPoints +------- + +This is another way to look at contours and its parts: ``bPoints`` behave very much like RoboFog points used to do. A point object has an incoming ``bcp``, an on-curve ("anchor point" fog called it) and an outgoing ``bcp``. This approach has been added for folks more at ease with the RoboFog structure. + +.. note:: + + If the contour contains series of off-curve points, ``bPoints`` won't help you. + +.. figure:: ../../images/contours_bpoints.jpg + :width: 300 px + :align: center + + bPoints with incoming and outcoming BCPs + +.. showcode:: ../../examples/howtos/understandingContours_03.py + +.. code:: + + ... + +.. seealso:: A description of the :doc:`bPoint <../objects/bPoint>` object. diff --git a/_sources/howtos/use_lib.rst.txt b/_sources/howtos/use_lib.rst.txt new file mode 100644 index 0000000..0d00883 --- /dev/null +++ b/_sources/howtos/use_lib.rst.txt @@ -0,0 +1,39 @@ +Using the lib +============= + +The lib is very much like a plain dictionary: you use keys to store stuff in it. The nice thing about them is that they save their contents in the font and are available (after the font is saved) to scripts the next time you open the file again. In FontLab the libs (because there are several) are stored in the ``.vfb`` source. In UFO-based fonts the ``font.libs`` end up in their own, XML based ``.plist`` files, inside th UFO package. The ``Glyph.libs`` end up in the ``.glif`` files. + +Which lib? +---------- + +Sometimes it is handy to store values directly in the font that needs them. Rather than saving something in a seperate file (which could easily get lost), you can store data like this in the lib. A ``RFont`` has a lib and each single ``RGlyph`` has a lib as well. RoboFog users might remember the various applications. It is likely that stuff will collect in the font and glyph libs, so it is wise to pay some attention to naming the entries. If you use undescriptive or generic names like ``a`` or ``mydata``, there's a chance that another script will overwrite the data. So the RoboFab developers propose to use the 'reverse domain name scheme' which works out something like this:: + + # storing something that belongs to a letterror script + aFont.lib['com.letterror.develop.markers'] + + # storing something that belongs to a aFoundry script + aFont.lib['com.aFoundry.bud.notes'] + +The lib is a flat dictionary. For RoboFog users: the RoboFog lib was nested and tried to be very clever. Unfortunately it meant that sometimes data would get lost in confusing situations. A flat dictionary solves that. + +.. note:: + + In FontLab version 4.5 and 4.6 there's a nasty bug which causes FontLab to crash after something has been added to the ``font.customdata`` or ``glyph.customdata`` fields. Unfortunately these fields were used to store the ``robofab.font.lib`` and ``robofab.glyph.lib`` data. We hope future versions of FontLab will address this. In UFO files the libs for font and glyphs work fine. + +aFont.lib +^^^^^^^^^ + +.. code:: + + # robofab manual + # Usethelib howto + # aFont.lib examples + +anyGlyph.lib +^^^^^^^^^^^^ + +.. code:: + + # robofab manual + # Usethelib howto + # anyGlyph.lib examples diff --git a/_sources/howtos/use_pens.rst.txt b/_sources/howtos/use_pens.rst.txt new file mode 100644 index 0000000..6a74709 --- /dev/null +++ b/_sources/howtos/use_pens.rst.txt @@ -0,0 +1,98 @@ +How to use pens +=============== + +On the :doc:`pens page <../objects/pens>` we discussed the different pens and their methods. Here we'll look at some practical applications of pens in RoboFab. + +Drawing stuff in glyphs +----------------------- + +Sometimes it is necessary to draw things in glyph with a script. Boxes around glyphs, logos, patterns. Whatever the reason, a pen is the way to do it. Rather than constructing all the Contour and Segment objects yourself (it's complex and it can be a pain to get it right), just use a pen to tell the Glyph what you want to draw. In order to make it somewhat easier to find the right pen for the right glyph, ``RGlyph.getPen()`` will return a pen object for the current environment. So if you're in FontLab ``getPen()`` returns a pen fit for drawing in FontLab RGlyphs. In UFO based fonts, ``getPen()`` returns a pen for drawing in UFO glyphs. This way you can keep the code free of environment specific imports. + +.. image:: ../../images/drawingexample.jpg + +.. showcode:: ../../examples/howtos/pens_00.py + +robofab.objects.pen.digestPen +----------------------------- + +Using pens to get to contour and outline data. + +DigestPointPen +^^^^^^^^^^^^^^ + +The ``DigestPointPen`` is a ``pointsPen`` and it doesn't draw anything, but collects all the coordinates and drawing instructions from ``glyph.drawPoints()``. When the drawing is done you can get to the data with ``myPen.getDigest()``. The result is a tuple with a series of coordinates and instructions. Because it is a tuple you can use it to compare it to other digests, for instance if you want to test if two glyphs are the same or not. + +.. showcode:: ../../examples/howtos/pens_01.py + +.. code:: + + ('beginPath', + ((140, -4), 'curve', True, None), + ((103, -4), None, None, None), + ((71, 30), None, None, None), + ((71, 69), 'curve', True, None), + ((71, 109), None, None, None), + ((103, 143), None, None, None), + ((140, 143), 'curve', True, None), + ((178, 143), None, None, None), + ((210, 109), None, None, None), + ((210, 69), 'curve', True, None), + ((210, 30), None, None, None), + ((178, -4), None, None, None), + 'endPath') + +DigestPointStructurePen +----------------------- + +The ``DigestPointStructurePen`` is very similar to the ``DigestPointPen``, but it only returns a tuple of the structure without any coordinates. This is very useful in comparing point structures between glyphs. For instance if you want to test if the glyphs can be used in interpolation. Using the same glyph as the example above, compare the results. + +.. showcode:: ../../examples/howtos/pens_02.py + +.. code:: + + ('beginPath', + 'curve', None, None, + 'curve', None, None, + 'curve', None, None, + 'curve', None, None, + 'endPath') + +robofab.objects.pen.filterPen +----------------------------- + +As you can see, pen objects are handy tools to get to the glyph data. The ``filterPen.py`` module contains a couple of pens which modify the contour when it is being drawn. Basically a ``filterPen`` controls another pen to do the drawing. + +FlattenPen and flattenGlyph() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Process the contours into a series of straight lines by flattening the curves. That means that a curve is drawn as a series of straight lines, approximating the curve. The length of the segment (and therefor the number of segments) determines the precision. The pen can be controlled to flatten with different lengths. ``FlattenPen`` works slightly differently from the PostScript "flattenpath" operator: flattenpath slices a cubic curve a fixed number of times, causing the segments to be of different lengths. The ``FlattenPen`` measures each segment and tries to get them all the same length. + +In order to make working with the ``FlattenPen`` easier, ``filterPen.py`` also has a convenience function ``flattenGlyph()``. This takes care of the one-pen-controlling-another thing, and replaces the current outlines with the filtered results: + +.. showcode:: ../../examples/howtos/pens_03.py + +.. image:: ../../images/flatten.gif + +Different values for ``d`` will result in different lengths for the segments drawn by the FlattenPen. + +ThresholdPen and thresholdGlyph() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``ThresholdPen`` only draws segments which are longer than a certain distance. This can be useful for filtering small unnecessary details from autotraced contours. Obviously this is not a replacement for a trained eye, more like a vacuum cleaner for points: + +.. showcode:: ../../examples/howtos/pens_04.py + +.. image:: ../../images/threshold.gif + +spikeGlyph() and halftoneGlyph() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``spikeGlyph`` and ``halftoneGlyph`` are two very graphic conversions. + +.. showcode:: ../../examples/howtos/pens_05.py + +.. image:: ../../images/spike.gif + +.. showcode:: ../../examples/howtos/pens_06.py + +.. image:: ../../images/halftone.gif diff --git a/_sources/howtos/use_transformations.rst.txt b/_sources/howtos/use_transformations.rst.txt new file mode 100644 index 0000000..6dc0c41 --- /dev/null +++ b/_sources/howtos/use_transformations.rst.txt @@ -0,0 +1,78 @@ +Using transformations +===================== + +Matrix transformations in RoboFab are done with the help of the matrix module from ``fontTools``. ``RContour``, ``RPoint``, ``bPoint``, ``RGlyph`` all have ``transform()`` methods which accept a matrix object. + +Transform objects and the Identity transform +-------------------------------------------- + +A Transform object from fontTools is a 2×2 transformation matrix plus offset, a.k.a. Affine transform. Transform instances are "immutable": all transforming methods, eg. ``rotate()``, return a new ``Transform`` instance. One way to make a new transform object is by importing the **Identity** transform from ``fontTools.misc.transform``. Identity is an instance of ``Transform`` and it is initialised to transform to itself (i.e. no visible transformation). The you modify the Identity object: each method (such as ``rotate()``, ``translate()`` etc) returns a new ``Transform`` object with the last transformation added to it. + +Oh no! Math! +^^^^^^^^^^^^ + +Transform objects are a fast and powerful way to do math with matrices. If you don't know what that means don't worry. If you follow the examples you can build Transform objects that rotate, translate and skew. Of course you can look up **affine transform** on google for some more in depth explanation of transformations. + +Angles +^^^^^^ + +Angles in all Python's math modules are measured in **radians** by default. A radian is a (perhaps) more scientific unit for angles than the regular "degrees", measuring the "distance travelled" over the circle rather than the angle. The length of a full circle (with radius 1) is 2 * pi. 90 degrees = 1/2 pi radians. One can easily be converted to the other using conversion methods from the math module:: + + import math + # example of a conversion of degrees to radians + print math.radians(90) + + # example of a conversion from radians to degrees + print math.degrees(math.pi) + +Example +^^^^^^^ + +.. showcode:: ../../examples/howtos/transformations_00.py + +.. code:: + + < Transform [1 0 0 1 0 0] > + < Transform [0.939692620786 0.342020143326 -0.342020143326 0.939692620786 0 0] > + +--------------------------- +Methods of Transform object +--------------------------- + +See the source code of ``fontTools.misc.transform`` for detailed descriptions and examples. + +.. py:function:: reverseTransform() + +Return a new transformation, which is the other transformation transformed by ``self``. ``self.reverseTransform(other)`` is equivalent to ``other.transform(self)``. + +.. py:function:: rotate(angle) + +Return a new transformation, rotated by ``angle`` (in radians). + +.. py:function:: skew(x, y) + +Return a new transformation, skewed by ``x`` and ``y`` (in radians). + +.. py:function:: scale(x=1, y=None) + +Return a new transformation, scaled by ``x`` and ``y``. The ``y`` argument may be ``None``, which implies to use the ``x`` value for ``y`` as well. + +.. py:function:: toPS() + +Return a string with the values of the transform written out in the PostScript manner: ``[1 0 0 1 0 0]``. + +.. py:function:: transform(other) + +Return a new transformation, transformed by another transformation. + +.. py:function:: inverse() + +Return the inverse transformation. + +.. py:function:: transformPoint((x,y)) + +Transform a point, i.e. apply the transformation to the point. + +.. py:function:: transformPoints(points) + +Transform a list of points. diff --git a/_sources/howtos/world.rst.txt b/_sources/howtos/world.rst.txt new file mode 100644 index 0000000..3c7dfd8 --- /dev/null +++ b/_sources/howtos/world.rst.txt @@ -0,0 +1,117 @@ +================================= +What is this robofab.world thing? +================================= + +RoboFab can operate in many different environments. When RoboFab is running in FontLab it needs to do different things than when you're using it on for instance Linux or Windows or OSX Python. ``robofab.world`` is a module which helps you by providing the objects and functions which are appropriate for the environment you're working in. + +------------- +Portable code +------------- + +Rather than include code in your scripts which try to figure out what functionality is available, and what machine, Python version etc. just ask ``roboFab.world``. Run a script in FontLab and you'll get RoboFab objects that interface with the FontLab fonts and glyphs. Run the same script outside FontLab, and you need objects that interface with UFO files. ``robofab.world`` makes the choosing of the right objects a bit more transparent. Just import from the world module and it will pick the right one. + +Using ``robofab.world`` is not compulsory -- you can load the objects from the modules yourself. In some cases ``robofab.world`` doesn't even load the objects you might need. But scripts that import from ``robofab.world`` can actually work in FontLab, but also outside of it. With a bit of care, your scripts can work on UFO and FontLab fonts without ever noticing the difference. That saves a lot of time and effort. + +---------------------- +Stuff in robofab.world +---------------------- + +Here are the objects and functions you can import from ``robofab.world``. If you want to see exactly when and which object are selected, have a look in the ``robofab.world`` source. + +^^^^^^^^^^^^^^^^^^^ +robofab.world.world +^^^^^^^^^^^^^^^^^^^ + +A collection of parameters about the world RoboFab works in. When the :py:mod:`robofab.world` module is loaded, the first time you call for it, it creates an instance of a special object which catalogs as much as possible about the environment it woke up in. This object is also called ``world``. It's simpler than it sounds really, have a look at the examples. + +In the Python IDE it looks like this:: + + >>> from robofab.world import world + >>> print world + [Robofab is running on darwin. + Python version: 2.3, + Mac stuff: X, + PC stuff: None, + FontLab stuff: False, + FLversion: None] + +In a FontLab macro (Mac FontLab) it looks like this:: + + >>> from robofab.world import world + >>> print world + [Robofab is running on mac. + Python version: 2.3, + Mac stuff: pre-X, + PC stuff: None, + FontLab stuff: True, + FLversion: 4.6.1/Mac] + +See the difference? + +^^^^^^^^^^^^^^ +OpenFont(path) +^^^^^^^^^^^^^^ + +``OpenFont`` is a function which opens a font. When called with a path it will open the font at that location. Without a path it will try to offer some appropriate interface to pick a font. In FontLab, ``OpenFont()`` gives you the standard font-opening-interface, and ``OpenFont(path)`` will open a FontLab font window for that font. Outside FontLab, for instance in the Python IDE, you get a file dialog to point at a UFO package. If you look at the source code of OpenFont, you'll see that it is not just one function, there are several for different kinds of environments. By importing ``OpenFont`` from ``robofab.world``, your script always has the right one and you don't have to change it when the script moves from one environment to the other:: + + >>> from robofab.world import OpenFont + >>> f = OpenFont() + >>> # dialog appears + >>> print f + < Font MyFont > + +.. note:: + + In places where there is no UI available, for instance when RoboFab is running on a Linux server, ``OpenFont(path)`` might try to import UI parts and fail. If you already know the path of a font, use ``RFont(path)`` instead: + + .. code:: + + >>> from robofab.world import RFont + >>> f = RFont('MyFont.ufo') + >>> print f + < RFont font for MyFontOT-Regular > + +^^^^^^^^^^^^^ +CurrentFont() +^^^^^^^^^^^^^ + +``CurrentFont`` is an old favorite from RoboFog. It returns a font object for the top most font or the last imported font. It is very useful to write short scripts that manipulate the current font in one way or the other, so you don't have to enter the font's name:: + + >>> from robofab.world import CurrentFont + >>> f = CurrentFont() + < RFont font for MyFontOT-Regular > + +^^^^^^^^^^^^^^ +CurrentGlyph() +^^^^^^^^^^^^^^ + +``CurrentGlyph`` is similar to ``CurrentFont``, except that it returns the top most glyph. ``CurrentGlyph`` returns ``None`` when there isn't a glyph window open:: + + >>> from robofab.world import CurrentGlyph + >>> g = CurrentGlyph() + < RGlyph for unnamed_font.L > + +^^^^^^^^^^ +AllFonts() +^^^^^^^^^^ + +``AllFonts`` returns a list with font objects for all fonts which are 'open' at the moment. In FontLab that means one ``RFont`` object for each font window. Outside FontLab it means a list of all font objects that exist at the moment. + +.. note:: + + It is possible to have more than one font object for the same UFO, so if you use ``AllFonts`` for UFOs you need to take that into account. ``AllFonts`` is easy if you want to do something to all open fonts: + + .. code:: + + >>> from robofab.world import AllFonts + >>> for f in AllFonts(): + >>> print f + < RFont for aFont-Plain.00 > + < RFont for aFont-Italic.00 > + < RFont for aFont-Bold.00 > + +^^^^^^^^^^^^^ +RFont, RGlyph +^^^^^^^^^^^^^ + +``RFont`` and ``RGlyph`` classes are also loaded by ``robofab.world``. In FontLab these objects will be imported from ``objectsFL.py`` (the FontLab implementation of the Unified Font Objects), and otherwise from ``objectsRF.py``, the UFO objects. diff --git a/_sources/index.rst.txt b/_sources/index.rst.txt new file mode 100644 index 0000000..c15fd6b --- /dev/null +++ b/_sources/index.rst.txt @@ -0,0 +1,60 @@ +Welcome to RoboFab +================== + +RoboFab is a Python library with objects that deal with data usually associated with fonts and type design. RoboFab has support for the `UFO font format`_. + +RoboFab is available as a couple of relatively easy to install packages. If you're just starting with RoboFab, or you just want to make UFO's, :doc:`this is the place to start `. + +For developers and folks who like to keep their fingers on the pulse of digital type, the RoboFab source code is available as a `git repository`_. The git version will be more up to date and might contain new features. + +.. _UFO font format: http://unifiedfontobject.org +.. _git repository: http://github.com/robofab-developers/robofab + +This documentation +------------------ + +.. py:module:: robofab + +.. toctree:: + :maxdepth: 1 + + intro/index.rst + objects/index.rst + howtos/index.rst + talks/index.rst + api/index.rst + +Object Model +------------ + +.. image:: ../images/logo.gif + +Here is a :doc:`handy map ` of the RoboFab objects. + +The Developers +-------------- + +RoboFab is developed and maintained by Tal Leming, Erik van Blokland, Just van Rossum (in no particular order) + +Contact +------- + +Email the RoboFab Consortium at `info@robofab.org `_. + +Copyrights +---------- + +This package is distributed under the BSD license. See the :doc:`license `. RoboFab is built in `Python`_. Parts of RoboFab use `fontTools`_, an OpenSource font toolkit by Just van Rossum. Parts of the RoboFab library are built to work with code from `FontLab`_, which is a product of Pyrus Inc. Parts of RoboFab implement the Property List file format in XML, copyright `Apple Computer`_. Parts of RoboFab implement tables and names from PostScript and the OpenType FDK, copyright `Adobe`_. + +.. _Python : http://python.org/ +.. _fontTools : http://sourceforge.net/projects/fonttools/ +.. _FontLab : http://fontlab.com/ +.. _Apple Computer: http://apple.com/ +.. _Adobe: http://adobe.com/ + +Indices & tables +---------------- + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` diff --git a/_sources/intro/dialogs.rst.txt b/_sources/intro/dialogs.rst.txt new file mode 100644 index 0000000..ba02ef1 --- /dev/null +++ b/_sources/intro/dialogs.rst.txt @@ -0,0 +1,142 @@ +Dialogs +======= + +Sometimes you need simple dialogs to get scripts to talk to the user. As RoboFab can run in many different environments, this dialog module tries to offer consistent functionality in all worlds. Most of the dialogs work in FontLab Mac/Win and Python IDE Mac. Some dialogs also work in Windows. This module offers the right kind of dialog for the environment you call them in. A bit like ``robofab.world`` helps you out by finding the right objects. + +Availability: + +- FontLab means that the dialogs are available in FontLab on either platform. +- Mac means that the dialogs are available in plain Python for OS9 as well as OSX. +- Windows means the dialogs are available in plain Python in Windows. + +.. py:function:: Message(message, title='RoboFab') + +A simple message dialog with just one OK button. It does not return any values: + +.. code:: + + from robofab.interface.all.dialogs import Message + Message("A Message From RoboFab") + +Available on FontLab, Macintosh. + +.. image:: ../../images/message_mac.jpg + +.. py:function:: AskString(prompt, value='', title='RoboFab') + +Asks for a string and return it. Returns ``None`` if the user cancelled. + +.. code:: + + >>> from robofab.interface.all.dialogs import AskString + >>> print AskString("Text for preview?") + "hello" + +Available on FontLab, Macintosh. + +.. image:: ../../images/askstring_mac.jpg + +.. py:function:: AskYesNoCancel(prompt, title='RoboFab', default=0) + +Returns ``1`` for 'Yes', ``0`` for 'No' and ``-1`` for 'Cancel'. ``default`` argument only available on Macintosh. + +.. code:: + + >>> from robofab.interface.all.dialogs import AskYesNoCancel + >>> print AskYesNoCancel("Do you really want to continue?", + >>> title='RoboFab', default=0) + -1 + +Available on FontLab, Macintosh. + +.. image:: ../../images/askyesnocancel_mac.jpg + +.. py:function:: GetFile(message=None) + +A standard select file dialog. Returns path if one is selected. Otherwise it returns ``None``. + +.. code:: + + >>> from robofab.interface.all.dialogs import GetFile + >>> print GetFile("Open Master") + path/folder/something + +Available on FontLab, Macintosh, PC. + +.. py:function:: GetFolder(message=None) + +A standard select folder dialog. Returns path if one is selected. Otherwise it returns ``None``. + +.. code:: + + >>> from robofab.interface.all.dialogs import GetFolder + >>> print GetFolder("Pick a directory...") + path/folder/something + +Available on FontLab, Macintosh, PC. + +.. py:function:: PutFile(message=None, defaultName=None) + +Save file dialog. Returns path if one is entered. Otherwise it returns ``None``. + +.. code:: + + >>> from robofab.interface.all.dialogs import PutFile + >>> print PutFile("Save this file as..") + path/folder/something + +Available on FontLab, Macintosh, PC. + +.. py:function:: SelectFont(message="Select a font:", title='RoboFab') + +Returns font instance if there is one, otherwise it returns ``None``. + +.. code:: + + >>> from robofab.interface.all.dialogs import SelectFont + >>> print SelectFont("Select a font:") + < the font you selected > + +Available on FontLab. + +.. image:: ../../images/selectfont_fl.jpg + +.. py:function:: SelectGlyph(font, message="Select a glyph:", title='RoboFab') + +Returns glyph instance from font if a glyph is selected. Otherwise it returns ``None``. + +.. code:: + + >>> from robofab.world import CurrentFont + >>> from robofab.interface.all.dialogs import SelectGlyph + >>> f = CurrentFont() + >>> if f is not None: + >>> print SelectGlyph(f, "select a glyph") + < the glyph you selected > + +Available on FontLab. + +.. image:: ../../images/selectglyph_fl.jpg + +.. py:function:: FindGlyph(aFont, message="Search for a glyph:", title='RoboFab') + +The ``FindGlyph`` dialog offers a list of the glyphs present in a font. A name or partial name can be types to navigate to the wanted glyph quickly. + +.. code:: + + >>> from robofab.world import CurrentFont + >>> from robofab.interface.all.dialogs import FindGlyph + >>> f = CurrentFont() + >>> if f is not None: + >>> print FindGlyph(f, "select a glyph") + < the glyph you selected > + +Available on FontLab. + +.. image:: ../../images/findglyph_fl.jpg + +.. py:function:: GetFolder(message=None) + +Select folder dialog. Returns the selected path if one is picked. Otherwise it returns ``None``. + +Available on FontLab, Macintosh, PC. diff --git a/_sources/intro/download.rst.txt b/_sources/intro/download.rst.txt new file mode 100644 index 0000000..2c3c629 --- /dev/null +++ b/_sources/intro/download.rst.txt @@ -0,0 +1,35 @@ +Download RoboFab +================ + +`RoboFab on GitHub `_ + +`download RoboFab zip `_ + +Cloning the repository +---------------------- + +If you are familiar with git, you can get the code straight from the repository:: + + git clone https://github.com/robofab-developers/robofab.git + + +RoboFab License Agreement +------------------------- + +Copyright (c) 2005-2012, The RoboFab Developers: + +- Erik van Blokland +- Tal Leming +- Just van Rossum + +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +- Neither the name of the The RoboFab Developers nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +`This is the BSD-3-Clause license `_ diff --git a/_sources/intro/gettingstarted.rst.txt b/_sources/intro/gettingstarted.rst.txt new file mode 100644 index 0000000..42e7a98 --- /dev/null +++ b/_sources/intro/gettingstarted.rst.txt @@ -0,0 +1,23 @@ +Getting Started with RoboFab +============================ + +Installing +---------- + +Installing RoboFab is pretty straightforward as installing Python libraries go. But considering this might be the first time you do this, here are a couple of things to pay attention to. First, have a look at the :doc:`installation notes `. + +Some remarks for FontLab 4.6 users on Mac OSX +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- In MacOSX, you need to have admin permissions to install robofab in MacOS 9 Python. +- If you've downloaded the MacOSX diskimage installer, first copy the entire thing to a nice, accessible place on your harddisk. The ``install.py`` script makes a link to the folder it's in, so if you were to run the install script from the mounted diskimage, RoboFab would be gone after you unmount the diskimage. + +FontLab Macros +-------------- + +RoboFab has some example scripts that show how it can be used in FontLab. In the RoboFab folder, there's a folder named ``Scripts``. In it are two folders that you can drag to FontLab's ``Macros`` folder. After restarting the application the ``Utils`` and ``RoboFabIntro`` folder will have been added to the macro list. + +Then what? +^^^^^^^^^^ + +It depends on your proficiency in scripting and operating fonteditors like FontLab. Some :doc:`notes on scripting <../howtos/scripting>` are available in the how to section. There's :doc:`this manual <../index>` which offers documentation, examples and background. Help with operating your font editor of choice is not available from this site or from the RoboFab developers. Read the manual. diff --git a/_sources/intro/glossary.rst.txt b/_sources/intro/glossary.rst.txt new file mode 100644 index 0000000..6521922 --- /dev/null +++ b/_sources/intro/glossary.rst.txt @@ -0,0 +1,10 @@ +Glossary +======== + +.. glossary:: + + Glyphmath + RoboFab objects support basic mathematical operations. Glyphs can be added, substracted and multiplied. The operations apply to all coordinates and all points. See also :doc:`how to use GlyphMath <../howtos/glyphmath>`. + + NoneLab + Name for RoboFab and python environment which is independent of FontLab. If something works in NoneLab it means that it can run on any platform that runs python with RoboFab installed. diff --git a/_sources/intro/history.rst.txt b/_sources/intro/history.rst.txt new file mode 100644 index 0000000..19bb55f --- /dev/null +++ b/_sources/intro/history.rst.txt @@ -0,0 +1,148 @@ +Release History +=============== + +A brief overview of what happened. + +September–December 2014 +^^^^^^^^^^^^^^^^^^^^^^^ + +RoboFab website (Documentation, How-Tos, ported to Sphinx. + + +November 30, 2009 - version 1.2 svn rev. 200 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In Python 2.6 ``as`` became a keyword. Some functions and methods in RoboFab used ``as`` as a parameter. This has been fixed. + +March 1, 2009 - version 1.2 +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This version implements and supports the UFO2 specification. Lots of work in the ``font.info`` area, new attributes. Also some renaming and moving of attributes. The ``objectsFL`` and ``objectsRF`` code takes care and does a lot of re-routing, but also prints warnings when you're using deprecated names. + +January 8, 2006 - version 1.1.2 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +RoboFab is now available from a public svn server at ``code.robofab.com``. A couple of fixes and changes were waiting to be checked in. Please look at the svn change log for a detailed list of changes. + +- In FontLab, ``AllFonts()`` will return a list of ``robofab.world.RFont`` objects for all open font windows. In NoneLab, ``AllFonts`` will raise a ``NonImplementedError``. ``AllFonts()`` can be imported from ``robofab.world``. The class magic which would also attempt to count font instances without a FontLab window has been removed. + +- When exporting to UFO in FontLab, the features are stored in the ``font.lib``. The order of the features is now also recorded. When a UFO is imported into FontLab, the features will be inserted in this order. If the order information is not present (as in all UFOs at the moment), the features are imported in alphanetical order like before. + +- Some updates to URLs in the documentation. + +- Note: these updates are in the svn version only at the moment. Building the releases and installers is not automatic. + +February 7, 2006 - version 1.1.1 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some changes in the **online** documentation. Note these changes are not part of the bundled documentation in the 1.1.1 release. + +- The default value for clear in ``font.newGlyph(glyphName, clear=True)``. This value is set to ``False`` in the ``objectsFL`` (FontLab) implementaion, but it is set to True in the NoneLab implementation. The documentation reflected the ``objectsRF`` version which led to confusion. The documentation has been updated. The default value for clear in the ``objectsFL`` implementation has been changed to ``True``. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +September 12, 2005 - version 1.1.1 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- The ``save`` argument in ``font.close`` is now ``False`` by default. Any scripts that rely on ``font.close()`` to save fonts should be modified. +- ``font.close(save=False)`` now suppresses the save dialog. +- ``GuessSmoothPointPen`` is now robust against closed contours containing just one point. +- Fixed a bug that was causing ``objectsRF`` to mark glyphs as dirty after simply being loaded. +- The ``GlyphSet`` in ``glifLib`` has a new ``getUnicodes`` method for quickly extracting unicodes from all GLIF files. +- The ``UFOReader`` in ``ufoLib`` has a new ``getCharacterMapping`` method for quickly extracting unicodes from all GLIF files. +- Fixed a ``RContour.clockwise`` bug that was causing incorrect results to be returned if the contour had overlapping points. +- Fixed a ``RFont.insertGlyph(..., as=name)`` bug that was causing the ``as`` name to not be applied in some cases. +- The result of ``glyph.copy()`` no longer has a parent. +- Setting ``italicAngle`` and ``slantAngle`` now forces the values to be floats. +- ``glyphNameSchemes`` now forces the conversion to big endian so the results will be the same on Windows and Mac. +- Components with negative scale values now return correct bounding boxes. +- ``dialogs.py`` no longer has a win32com dependency when used in FontLab Windows. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +February 7, 2005 - version 1.1 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Fixed a minor rounding error in ``flPen.py`` that was allowing unrounded data to be passed to FontLab. +- ``objectsRF.RComponent`` decomposes properly now. +- Added new ``filterPen.py`` to pens: a module with some useful and sample pens illustrating non-drawing applications of pen objects. ``StatsPen``: a pen returning the length of the contour, ``FlattenPen``: a cubic path flattener. And a couple of helpers to make filtering easier. +- ``robofab.features`` but that may be moving to a private location... +- ``RInfo`` now has ``createdBy``, ``weightValue``, ``weightName`` and ``widthName`` attributes. These are also now written into ``info.plist`` in UFOs. +- ``RGlyph`` has a fun new rasterize method. +- ``RContour`` now has rotate and skew methods. +- New ``robofab.path.intersect`` module for calculating intersections. +- New ``FindGlyph`` dialog added to ``dialogs.py``. This dialog is similar to ``SelectGlyph``, but it contains a search field. Very handy when working with large fonts. +- Setting ``objectsFL.unitsPerEm`` is now buffered against possible float values +- Added UNIX ASCII (PFA) as a generating option in ``RFont`` (use ``unixascii`` as the type in the generate method). It has been here all along, but it was incorrectly labeled as PC Type 1 ASCII. +- Retrieving groups from a VFB is now more stable. +- ``RFont.insertGlyph`` has a new ``as=something`` argument in order to easily insert one glyph under a different name. +- ``RGlyph`` interpolation and glyph math have been completely rewritten. Now the methods are much more flexible about point types and off curve point counts. The methods are still very strict regarding the count of on curve points. In addition to being much more flexible, it is also much faster. +- ``RGlyph.isCompatible`` returns results that follow the same logic as ``RGlyph.interpolate`` +- ``RContour.interpolate`` and the math methods in ``RContour``, ``RSegment``, ``RPoint``, ``RAnchor`` and ``RComponent`` have all been deprecated. +- ``RGlyph.note`` is now properly encoded. +- A provision for alternate .glif namingschemes has been added. During the writing of UFO the user can now specify a function (for instance ``robofab.tools.glyphNameSchemes.glyphNameToShortFileName``) to create ``.glif`` filenames for glyphs. Previously all glyphnames mapped to filenames directly, which made it impossible to export glyphs with long names in some pythons. The default glif naming scheme in ``ObjectsFL`` has been set to the aforementioned ``glyphNameToShortFileName``, check the module for a detailed description of the algorithm. Note that this only affects new exports. Existing UFO's and ``.glifs`` are not changed. See `How to use glyph naming schemes`_. +- Fixed a bug that could pontially cause a GLIF to be saved outside of the proper UFO. +- New scripts located in ``robofab/Scripts/RoboFabUFO``: ``DumpOneGlyphToGlif.py``, ``DumpOneGlyphToUFO.py``, ``ExportFontToUFO.py``, ``ImportFontFromUFO.py``, ``ImportOneGlyphFromUFO.py`` +- Bug in script ``GenerateKernProof.py`` fixed. +- ``RFont`` now has a handy ``getReverseComponentMapping`` method for getting a reversed component mapping. +- ``AllFonts`` bugs squashed. +- ``plistlib`` modified to by Python 2.2 compatible +- Glyph order is now stored and read from ``font.lib["org.robofab.glyphOrder"]``. Importing a UFO into FontLab now follows this order. +- Raw FDK-style OT feature code is now stored in ``font.lib["org.robofab.opentype.classes"]`` and ``font.lib["org.robofab.opentype.features"]`` in UFOs. This data is stored in the OpenType fields in FontLab files. +- ``robofab.world`` no longer prints nag during import. +- Fixed bug in ``objectsRF.RFont.save`` that was occasionally (very, very rarely) forcing save operations to be considered save as operations. +- Added deprecation warnings to ``family.py`` and ``featureLib.py``. +- Added warning to ``nameTable.py``. +- Removed ``properties.py``. +- Removed unused ``Point`` and ``Offset`` classes from ``objectsBase``. +- Fixed a bug that would raise an error in ``robofab.interface.all.dialogs.AskString``. +- Backported RoboFab to Python 2.2.1. This is now the oldest version of Python we support. Python 2.2 is not supported. +- RoboFab now includes a Python 2.2 compatible version of ``sets.py`` (found here). In Python 2.3+ the sets from the standard lib will be used in place of this version. +- Reworked the way ``RPoint`` determines its type attribute in ``objectsFL``. +- Patched a small bug in ``BaseContour.draw`` that occured when a contour begins with a ``qcurve`` in FontLab. +- Removed support for drawing with antique RoboFab pens. Only FontTools pens are supported now. +- Removed support for drawing with antique RoboFab pens. Only FontTools pens are supported now. +- Components now have a read-only ``box`` attribute. + +.. _How to use glyph naming schemes : # + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +March 26, 2004 - version 1.01 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Renamed the folder with utility scripts for FontLab to ``RoboFab Utils`` as not to overwrite any other folders named ``Utils`` which might live in the FontLab macros folder. +- Fixed a problem with ``glyph.box`` which would show up in some cases in plain Python use of RoboFab with glyphs which have anchors outside of the horizontal bounds of the glyph. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +March 14, 2004 - version 1.0 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +First public release. + +^^^^^^^^^^^^ +January 2004 +^^^^^^^^^^^^ + +We've done some projects using RoboFab at the center and it's fast to work with and reliable. We considered ways to reschedule the conference and couldn't plan anything for a couple of unrelated but unchangeable reasons. We decide for a release. + +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +September 2003: RoboThon '03 +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Worked very hard to get RoboFab 1.0b1 ready for the RoboThon conference in September. The RoboThon was cancelled at the last minute to make room for hurricane Isabel. We soon released the beta to a small group but the missed conference made it difficult for folks to get started. + +^^^^^^^^^^^^^^^^^^^^^^^^^ +July 2003: New Fileformat +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Summer 2003 we started defining the UFO file format, using GLIF for glyph information and Apple's ``.plist`` (also XML based and entirely cross platform) for any other data as listings, indices, etc. + +^^^^^^^^^^^^^^^^^^^^^^^ +April 2003: New Objects +^^^^^^^^^^^^^^^^^^^^^^^ + +April 2003 we started new objects to live on top of the FontLab objects. Just van Rossum started work on the GLIF file format. + +^^^^^^^^^^^^^^^^^^^^ +February 2003: Start +^^^^^^^^^^^^^^^^^^^^ + +RoboFab was started sometime during the TypoTechnica in Heidelberg, 2003. Tal Leming, Erik van Blokland and Just van Rossum combined their FontLab code into a new library. At first it was an odd collection of fixes and workarounds. diff --git a/_sources/intro/index.rst.txt b/_sources/intro/index.rst.txt new file mode 100644 index 0000000..a2e8ea2 --- /dev/null +++ b/_sources/intro/index.rst.txt @@ -0,0 +1,18 @@ +Introduction +============ + +.. toctree:: + :maxdepth: 1 + + intro.rst + summary.rst + download.rst + install.rst + gettingstarted.rst + history.rst + limitations.rst + links.rst + tools.rst + dialogs.rst + ufo.rst + glossary.rst diff --git a/_sources/intro/install.rst.txt b/_sources/intro/install.rst.txt new file mode 100644 index 0000000..7628efe --- /dev/null +++ b/_sources/intro/install.rst.txt @@ -0,0 +1,96 @@ +Installation notes +================== + +Installing RoboFab on Mac OSX +----------------------------- + +1. Download RoboFab and put it wherever you want it to live on your hard drive. Many people make a RoboFab folder in ``/Applications``. + +2. Go to your ``Applications/Utilities`` folder. + +3. Open Terminal. + +4. Once the terminal is open, type ``python`` with a space after it. + +5. Drag the ``install.py`` script from the RoboFab folder into the line that you just typed in the terminal. It should now look something like this (with your name, rather than ``Tinkywinky``):: + + python /Users/Tinkywinky/RoboFab/install.py + +.. note:: + + If you have different versions of Python in your system, you need to explicitly tell with which version of Python you want to install. The command would look like this:: + + python2.6 /Users/Tinkywinky/RoboFab/install.py + +6. Hit the return key and the following should be printed in the terminal:: + + Installing RoboFab: about to write a path to '/Users/Tinkywinky/RoboFab/ + Lib' in '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/ + python2.7/site-packages/robofab.pth'... + Robofab is now installed. + (Note that you have to run the install script again if you move your RoboFab folder) + +7. Restart FontLab if you had it open during this process. + +This will install RoboFab for the system Python, which is what FontLab Studio uses. + +Permissions +----------- + +Make sure you have admin permissions on the machine when you install the various packages. When installing as a normal priviliged user, it can sometimes happen that certain files can't be written, and the installation remains incomplete. The most common problem is that one or two preference files need to be written, but the current user does not have enough permissions to delete them. Read the traceback, locate the file, delete, install again. + +About install.py +---------------- + +In the package, on the same level as this read me there's a ``install.py`` script. Running this script creates a file named ``robofab.pth`` in site-packages. This ``robofab.pth`` file contains the path to the current location of the RoboFab package. It does not copy the RoboFab package to ``site-packages`` itself, you need to keep the RoboFab package. Also: if you *move* the RoboFab folder to some other location (or rename any of the directories the RoboFab folder is nested in), you have to run the ``install.py`` script again to update the path. + +Dependencies +------------ + +Some parts of RoboFab depend on other Python modules and packages. These need to be installed as well. + +**FontTools** + Robofab requires Just van Rossum's FontTools package (not to be confused with Apple Inc's set of tools for fonts with the same name). Download the latest snapshot of FontTools at `fonttools.sf.net`_. + +**dialogKit** + Some FontLab scripts in RoboFab require Tal Leming's dialogKit UI package. Download the latest version of dialogKit at `github.com/typesupply/dialogKit`_. + +.. _fonttools.sf.net: http://fonttools.sf.net/ +.. _github.com/typesupply/dialogKit: http://github.com/typesupply/dialogKit + +RoboFab bundled with FontLab Studio 5 +------------------------------------- + +FontLab Inc. has been granted permission to bundle RoboFab with FontLab-the-application. They have not done so. The reason is not clear. + +Installing FontLab scripts +-------------------------- + +RoboFab has two folders of demo scripts and utilities which can be used in FontLab. Copy the contents of the **Scripts** folder to the ``FontLab/Macros`` folder to make them available to FontLab. + +Installing on Windows +--------------------- + +Installing RoboFab on windows should be pretty straightforward. RoboFab is backwards compatible to Python 2.2.1, but not 2.2. RoboFab now includes a Python 2.2 compatible version of ``sets.py``. + +Installing on other platforms +----------------------------- + +Place the robofab directory in a place where you can leave it for a while. Not on the desktop or a temporary download folder. Run ``install.py`` in a Python interpreter. + +Initial testing +--------------- + +Open a Python interactive interpreter window.:: + + import robofab + # notice, all lowercase! + +If you don't get an traceback, you're good to go. + +In ``Scripts/RoboFabIntro/`` there are some test scripts, simple examples and some utilities. Read the source to learn more about what the examples do and where they want to run. + +Detailed unittesting +-------------------- + +Robofab has unittesting to make sure all parts function properly. If you don't know what unittesting is, don't sweat it. If you're interested, go to ``robofab/test/runAll.py``. diff --git a/_sources/intro/intro.rst.txt b/_sources/intro/intro.rst.txt new file mode 100644 index 0000000..cb99924 --- /dev/null +++ b/_sources/intro/intro.rst.txt @@ -0,0 +1,54 @@ +RoboFab Intro +============= + +RoboFab is a **library** of Python code for manipulation and storage of font and glyph related data. RoboFab implements a new font file format, the :doc:`Unified Font Objects ` or .ufo for short. UFO is a format for **font sources** (similar to something like .fog or .vfb) except that UFO is XML based (see :ref:`Glyph Interchange Format `), readable, well documented and easily extended to contain different kinds of data. + +Long term sources +----------------- + +Traditionally, font editors have their own file formats to store the work in progress. Generated fonts are optimised for size and speed and they have no extra room to store all the additional information one needs during the design of a font (for instance background layers, notes, information for other font formats). When a company stops working on their application (it happens), the binary source files become a burden. Not immediately, but soon enough as system updates make the last version of the program impossible to run. When that happens, all the binary source files are impossible to read. The formats are not or badly documented. They've locked themselves and your work is gone. Type design is a long term endeavour and it makes sense to store font source material in a long term format. UFO is our idea of how such a format should look like: XML based, object oriented and flexible. Text is just so much easier to handle. + +Unified Font Objects +^^^^^^^^^^^^^^^^^^^^ + +RoboFab reads and writes UFO, but it also provides a range of Python objects to work with these Unified Font Objects. We have implemented the UFO objects for use in FontLab (based on top of FontLab's own objects) and another one which implements the UFO objects for use in a plain-Python environment, NoneLab. That means you can access and manipulate font and glyph data in Python without running a font editor (but it has some other drawbacks). It's possible to write scripts with RoboFab that work the same in FontLab as they do in a plain Python environment. Unified Font Objects can store quadratic and bezier splines. + +RoboFab environments +-------------------- + +Parts of RoboFab can be used in FontLab, other parts work outside FontLab, in normal Python interpreters. Some parts work in both. This is a powerful feature of RoboFab, but it can sometimes be a bit confusing. Have a look at :doc:`the world module <../howtos/world>` for some help in making scripts that work everywhere. + +RoboFab in plain Python +^^^^^^^^^^^^^^^^^^^^^^^ + +After RoboFab is installed you can write plain non-FontLab Python scripts that open, manipulate and save .ufo files. Through the RoboFab :doc:`objects <../objects/objects>` you have access to all data in the font: names, glyphs, contours, widths, kerning, the lot. Use the :doc:`objects overview <../objects/objects>` or the :doc:`objects map <../objects/model>` to get an idea of what these things can do. Plain Python can be a Python IDE, or a python command line interpreter. RoboFab runs on any Python 2.2.1+ installation, Linux, Unix, Mac OSX, MacOS9, Windows. `Python ports to lots of platforms`_ and so does RoboFab. + +.. _Python ports to lots of platforms: http://python.org/download/ + +RoboFab in FontLab's Python +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +RoboFab can also run in FontLab and transparently implements the RoboFab object structure on top of the FontLab objects. That means that with RoboFab installed you can talk to FontLab fonts using the same methods and attributes as you use to write scripts for UFO fonts. The RoboFab objects in FontLab can manipulate the font data you see in the FontLab windows. Some RoboFab objects in FontLab have extra attributes and methods to deal with FontLab specific functionality. For example font generation, guides and access to the underlying FontLab objects. + +RoboFab and UFO +^^^^^^^^^^^^^^^ + +RoboFab Font objects can export and import the UFO format. So you can write scripts in FontLab that export data to UFO, and other scripts that edit these UFO's, and then later import the UFO back into FontLab. + +What RoboFab is not.. +--------------------- + +Not entirely RoboFog MkII +^^^^^^^^^^^^^^^^^^^^^^^^^ + +RoboFab is not a port of **RoboFog** to OSX, nor is it a complete font editor with interfaces, font and glyph windows etc. It is a toolkit that you can use to build your tools with. You can start by using RoboFab to make scripting in FontLab easier. But you can also use RoboFab to build elaborate tools (for instance **MetricsMachine**) that read and write UFO fonts and work on the data. Other RoboFab based tools are under construction. + +Not entirely RoboFog Compatible +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +We've poured all our experience from writing RoboFog into the RoboFab objects. You will recognise a lot. But the font world has grown a lot more complex since Fontographer 3.5 so RoboFab objects need to deal with a lot more than their RoboFog ancestors. Your RoboFog scripts won't work with RoboFab, sorry. But they're structured quite similarly and you won't have much trouble adapting. We thought about building objects with the RoboFab API for RoboFog, but their functionality depends too much on features that were introduced after Python 1.5.2. It would be too complex. But we've provided an alternative: export scripts for RoboFog to UFO format, so that you can write UFOs for all your RoboFog sources and use them in the new UFO tools. + +Where next? +----------- + +First you could :doc:`download` the library and install it. Then you could browse through this documentation and see what the various :doc:`objects <../objects/index>` are, what they can do etc. You could have a look at :doc:`a discussion on scripting <../howtos/scripting>`. diff --git a/_sources/intro/limitations.rst.txt b/_sources/intro/limitations.rst.txt new file mode 100644 index 0000000..bb2bedd --- /dev/null +++ b/_sources/intro/limitations.rst.txt @@ -0,0 +1,50 @@ +Limitations +=========== + +An overview of known problems, bugs and implementation limits. These are issues we are aware of. Some of them are things we have to fix in RoboFab, others are limitations that are just part of the world we have to work in. + +FontLab +------- + +Known problems in FontLab 4.6.1 + +flfont.customdata, flglyph.customdata +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +There is a bug in FontLab which caused FontLab to crash shortly after Python has written something in the ``flfont.customdata`` or ``flglyph.customdata`` fields. RoboFab uses the customdata fields to store the ``font.lib`` and ``glyph.lib``. RoboFab is just using the functionality of these fields in FontLab, there's nothing we can do to fix it in RoboFab. The problem has been reported to the FontLab developers. + +.. note:: FontLab Studio 5 probably has a new attribute for font and glyph objects to store arbitrary Python data. This attribute will replace the customdata attribute. At the time of the 1.1.1 release we have not tested this attribute. We expect a future release to make use of them. + +Multiple Master +^^^^^^^^^^^^^^^ + +RoboFab glyphs do not offer direct access to FontLab's Multiple Master-masters. If you need access to that data, use the ``glyph.naked()`` method to get to the FontLab glyph object which have access. + +.. note:: If you're considering scripting complex interpolation systems, have a look at `Superpolation`_. + +.. _Superpolation: http://superpolator.com/ + +UFO format +---------- + +Known problems or limitations in the UFO format, RoboFab version 1.0b1 and 1.0. + +Export of OT features +^^^^^^^^^^^^^^^^^^^^^ + +RoboFab does not automatically export the feature descriptions from FontLab to UFO. The ``featureLib.py`` offers some tools to export the feature text to the ``font.lib`` and import them from the lib as well, but this needs to be called separately after reading and before writing the UFO. Or export all features to a separate ``.fea`` file. + +Macroman encoded XML files from UFO Exporter in RoboFog +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Not a problem, but just something to be aware of: UFO files exported from the UFO Exporter scripts in **RoboFog** are text files with macroman text encoding. The XML files identify the encoding as such and XML interpreters seem to respect and understand this. UFO files exported written by the UFO writers in RoboFab use UTF-8 as default encoding for the XML text. The macroman export is necessary because encodings are not supported in Python 1.5.2. + +Objects +------- + +Known problems with Objects. + +GlypMath on Contour, Segment, Point in FontLab +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``Contour``, ``Segment``, ``Point`` and ``BPoint`` objects in ``objectsFL`` (the objects you get when you use RoboFab in FontLab) do not have GlyphMath operators. All GlyphMath operations in FontLab are handled by the ``Glyph`` object and then quickly deferred to objects from ``objectsRF`` which do know how to handle GlyphMath operations. This is not necessarily a bug, but an effect of differences between the way RoboFab objects work in FontLab and how they work in plain Python. diff --git a/_sources/intro/links.rst.txt b/_sources/intro/links.rst.txt new file mode 100644 index 0000000..b3aa62c --- /dev/null +++ b/_sources/intro/links.rst.txt @@ -0,0 +1,26 @@ +Links +===== + +Online resources +---------------- + +- `Join the RoboFab Google group `_ +- `The FontLab Python page `_ +- `Unofficial FontLab Python documentation `_ + +Tools +----- + +- `The FontTools home at sourceforge.net `_ +- `The TTX page at LettError.com `_ +- `MetricsMachine from TypeSupply `_: Industrial Strength Metrics for OS X. +- `Lots of code from TypeSupply `_: Tools for developing tools and writing nice apps in Python. +- `Superpolator.com `_: Infinite interpolation for RoboFab and FontLab. +- `FontForge `_: A free font editor with Python and UFO support. +- `The FontLab home page `_ + +Python +------ + +- `The main Python site Python.org `_ +- `The Mac OSX section on Python.org `_ diff --git a/_sources/intro/summary.rst.txt b/_sources/intro/summary.rst.txt new file mode 100644 index 0000000..22a0feb --- /dev/null +++ b/_sources/intro/summary.rst.txt @@ -0,0 +1,12 @@ +Executive Summary +================= + +RoboFab is the result of over 6 man-years of concentrated coding. The package combines a solid Pythonic API with over 40 standardized classes of objects for font and glyph related data. With RoboFab installed, the scripter will find it easier to produce scripts, API standardization means fewer things to remember or look up -- eventhough RoboFab comes with extensive documentation and example code. + +The Font/Glyph/Contour/Point model can be tailored to the needs of the scripter, manipulating data from glyph to glyph or font to font and addressing the outline data point by point, as offcurve/oncurve segments or as conventional knots with incoming / oncurve / outgoing attributes. RoboFab's Kerning object delivers the kerning data as a standard Python dictionary object. The Lib objects will soon take advantage of FontLab's new PythonDict field for storing Python data inside FontLab .vfb sources. + +RoboFab's pen objects (an implementation of fontTools' pen classes) provide a powerful method to interface with glyph data, either for actual drawing (for instance on screen, or some sort of vector based file format), complex comparisons, transformations and filtering. + +RoboFab offers a large selection of standardised UI dialogs, ranging from plain messaging to very powerful font and glyph retrieval functionality. + +RoboFab also brings extensive support for import and export of glyph and font data to UFO, an open industry standard based on XML. UFO makes it possible to, for instance, store text versions of glyphs and fonts in large SQL databases and apply standard text source management tools (such as cvs, diff) to glyphsets. diff --git a/_sources/intro/tools.rst.txt b/_sources/intro/tools.rst.txt new file mode 100644 index 0000000..591fede --- /dev/null +++ b/_sources/intro/tools.rst.txt @@ -0,0 +1,54 @@ +Tools +===== + +The RoboFab Tools directory contains a groups of useful and sometimes stray bit of code which don't fit anywhere else. + +robofab.tools.toolsAll +---------------------- + +ToolsAll contains useful functions for any and all implementation of RoboFab. It does (or should not) contain any platform or version specific code. Some of this code is used by other parts of RoboFab. The user serviceable parts are discussed here. + +.. py:function:: toolsAll.readFoundrySettings(dstPath) + +Read the foundry settings xml file and return a keyed dict. The idea is that a foundry will have certain, ofter recurring preferences for some fields in fonts. For instance foundry names, codes etc. These can be stored in ``.plist`` format, at a particular location. It's up to the user to make sure the values make sense and to keep track of the file. + +.. py:function:: toolsAll.fontToUFO(src, dst, fileType=None) + +Open a font binary pointed to by src, decompile it using fontTools and write a UFO at location dst. If no filetype is given, ``fontToUFO`` attempts to guess the type. Valid types are TTF and "Type 1". While this function does a good job at extracting contours and basic font information, it is possible that not all values are extracted. Please refer to the result UFO for a precise overview. + +robofab.tools.toolsFL +--------------------- + +Tools for use within FontLab. Some of the functions in ``toolsFL`` are available through ``robofab.world``. The user serviceable parts are discussed here. + +.. py:function:: toolsFL.AppFolderRenamer() + +``AppFolderRenamer`` renames the directory the FontLab application is in. It attempts to add the version number of the application to the folder name. This can be helpful to keep different versions of FontLab separated. + +.. warning:: It messes with the paths of your app, if you have items that hardwired to this path you'd be in trouble. + +.. py:function:: toolsFL.MakeTempFont(font, dupemark=None, removeOverlap=True, decompose=True) + +Save the current FL Font, + +- close the file +- duplicate the file in the Finder (icon looks weird, but it works) +- open the duplicate +- decompose the glyphs +- remove overlaps +- return the ``Font`` object + +``font`` is either a FL ``Font`` or RF ``RFont`` object. + +.. note:: It will overwrite older files with the same name. + +.. warning:: Doesn't check if the filename is getting too long. + +.. py:function:: toolsFL.makePSFontName(name) + +Create a PostScript filename out of a regular PostScript fontname, using the old fashioned macintosh 5:3:3 convention. + +robofab.tools.toolsRF +--------------------- + +These are no special tools for RF or NoneLab use at the moment. diff --git a/_sources/intro/ufo.rst.txt b/_sources/intro/ufo.rst.txt new file mode 100644 index 0000000..58895c1 --- /dev/null +++ b/_sources/intro/ufo.rst.txt @@ -0,0 +1,32 @@ +UFO Overview +============ + +Another font format? +-------------------- + +No. The RoboFab developers felt the need for a flexible, text based (XML) format to store data related to typedesign. RoboFab Python objects work with UFO files, but the UFO specification is open: others can write implementations of the UFO format in other languages for other purposes. The UFO format is documented `here`_. + +.. _here: http://unifiedfontobject.org/ + +.. _glif: + +GLIF +---- + +Glyphs and glyph related data is stored in a GLIF file which lives with its friends in a folder. Just van Rossum developed the XML format and described the tags in great detail here. A GLIF file describes all parts of the glyph: contours, points, off curves, on curves, width, even the glyph lib is stored here. RoboFab reads and writes GLIF. You could email a glyph by including the text in the email body. GLIFs have been sent through text chats and even SMS text messaging. GLIFs could be printed out on paper, stored, typed in after a 1000 years and all the data would still be present. + +GlyphSet +-------- + +A GlyphSet is an object which manages the GLIF files. It can make an index of all GLIF files in a folder and store it in a seperate .plist file in which glyph names are mapped to GLIF file names. When a GlyphSet is asked for a particular Glyph, it can refer to the index and retrieve the right file. GlyphSet is "lazy loading", it will only read and parse XML for Glyphs that are asked for. Font objects in NoneLab use GlyphSet to access and write the GLIFs. + +Pen Protocol +------------ + +The Pen Protocol is a fast and versatile way to get data in and out of glyphs, without having to know their internal structure. RoboFab uses Pen objects a lot. More on the Pen Protocol here. +Unified Font Objects + +By standardising the API of the RoboFab objects, scripts become more portable between different font applications. This means saving time and effort which can be spent more creatively. Fonts, glyphs and contours aren't going to change a lot. More likely, stuff will be added to it and exist next to the other data. RoboFab and UFO can deal with the future. +Unified Font Objects Consortium + +The RoboFab developers extend an invitation to all other font tool developers to support the UFO file format, and perhaps if possible the UFO object API as well. diff --git a/_sources/objects/RAnchor.rst.txt b/_sources/objects/RAnchor.rst.txt new file mode 100644 index 0000000..c3c9f6b --- /dev/null +++ b/_sources/objects/RAnchor.rst.txt @@ -0,0 +1,87 @@ +RAnchor +======= + +.. image:: ../../images/RAnchor.gif + +Usage +----- + +.. showcode:: ../../examples/objects/RAnchor_00.py + +.. code:: + + < RGlyph for RoboFab Demo Font.A > + [< RAnchor for RoboFab Demo Font.A.anchors[0] >] + +Description +----------- + +Anchors are single points in a glyph which are not part of a contour. Anchors have a name and a position, and they're used as connection points for :doc:`Components `. In FontLab the anchors have a special appearance and can be edited. Anchors are stored in GLIF as single, named, ``moveto``'s. i.e. any single, named ``moveto`` in GLIF will become an anchor in FontLab. RoboFab's own ``font.generateGlyph()`` also uses the anchors to assemble the components. + +Attributes +---------- + +.. attribute:: index + +The index of the anchor. (read only) + +.. attribute:: position + +The position of the anchor ``(x, y)``. + +.. attribute:: x + +The ``x`` position of the anchor. + +.. attribute:: y + +The ``y`` position of the anchor. + +.. attribute:: name + +The name of the anchor. + +Attribute examples +------------------ + +.. showcode:: ../../examples/objects/RAnchor_01.py + +Methods +------- + +.. function:: copy() + +Return a deepcopy of the object. + +.. function:: move((x, y)) + +Move the anchor of the ``bPoint`` to ``(x,y)``. The relative coordinates of the ``bcpIn`` and ``bcpOut`` will remain the same, which means that in fact, they move the same distance. + +.. function:: scale((x, y), center=(0, 0)) + +Scale the anchor. + +.. function:: round() + +Round the coordinates to whole integers. + +.. function:: draw(aPen) + +Draw the object with a RoboFab segment pen. + +.. function:: drawPoints(aPen) + +Draw the object with a point pen. See :doc:`how to use pens <../howtos/use_pens>`. + +.. function:: transform(matrix) + +Transform this point. Use a Transform matrix object to mess with the point. See :doc:`how to use transformations <../howtos/use_transformations>`. + +Method examples +--------------- + +.. code:: + + # robofab manual + # Font object + # method examples diff --git a/_sources/objects/RComponent.rst.txt b/_sources/objects/RComponent.rst.txt new file mode 100644 index 0000000..99c773d --- /dev/null +++ b/_sources/objects/RComponent.rst.txt @@ -0,0 +1,92 @@ +RComponent +========== + +.. image:: ../../images/RComponent.gif + +Usage +----- + +.. showcode:: ../../examples/objects/RComponent_00.py + +.. code:: + + < RComponent for Excellent-Regular.adieresis.components[0] > + < RComponent for Excellent-Regular.adieresis.components[1] > + +Description +----------- + +A component can be a part of a glyph and it is a reference to another glyph in the same font. With components you can make glyphs depend on other glyphs. Changes to the ``baseGlyph`` will reflect in the component as well. Fontographer and RoboFog called them **composites**. The **parent** of a component is usually a glyph. Components can be decomposed: they replace themselves with the actual outlines from the ``baseGlyph``. When that happens the link between the original and the component is broken: changes to the ``baseGlyph`` will no longer reflect in the glyph that had the component. + +Attributes +---------- + +.. attribute:: baseGlyph + +The name of the glyph the component points to. The glyph is assumed to be present in the same font. + +.. note:: In FontLab this attribute is read-only. + +.. attribute:: index + +The index of the component in the list of components in the parent glyph. i.e. the first component in a glyph has index ``0``. + +.. attribute:: offset + +The offset vector ``(x, y)``. The distance the component has been moved. + +.. attribute:: scale + +The scale ``(x, y)``. The distance the component has been moved. + +.. attribute:: box + +The bounding box for the component. (read only) + +Attribute examples +------------------ + +.. showcode:: ../../examples/objects/RComponent_01.py + +.. code:: + + a + dieresis + +Methods +------- + +.. function:: decompose + +In the parent glyph replace this component object with the actual contours. This practically ends the existence of the component object. + +.. function:: move((x, y)) + +Move the component to position ``(x, y)``. + +.. function:: draw(aPen) + +Draw this component with ``aPen``. + +.. function:: drawPoints(aPointPen) + +Draw this component with ``aPointPen``. + +.. note:: Both these drawing methods are usually called by ``aGlyph.draw()`` and ``aGlyph.drawPoints()`` as part of the drawing process. + +.. function:: copy + +Return a deep copy of the object. + +.. function:: setChanged + +Call to indicate that something about the component has changed. + +Method examples +--------------- + +.. code:: + + # robofab manual + # Component object + # method examples diff --git a/_sources/objects/RContour.rst.txt b/_sources/objects/RContour.rst.txt new file mode 100644 index 0000000..9a9a932 --- /dev/null +++ b/_sources/objects/RContour.rst.txt @@ -0,0 +1,149 @@ +RContour +======== + +.. image:: ../../images/RContour.gif + +Usage +----- + +.. showcode:: ../../examples/objects/RContour_00.py + +.. code:: + + < RContour for Mailer-Regular.a[0] > + +Description +----------- + +``RContour`` is an object for, well, contours. A contour is a single path of any number of points and shape. A glyph usually consists of a couple of contours, and this the object that represents each one. The ``RContour`` object offers access to the outline matter in various ways. The parent of ``RContour`` is usually ``RGlyph``. + +Understanding Contours and outlines +----------------------------------- + +The way outline data is organised in RoboFab, and how the various objects relate is described here: :doc:`understanding contours <../howtos/understanding_contours>`. + +.. note:: If you want to add new contours to a glyph it's easier to :doc:`draw them with a pen <../howtos/use_pens>` than to construct the shapes from segments. + +Attributes +---------- + +.. attribute:: index + +The index of the contour in the Glyph. + +.. attribute:: selected + +Returns ``1`` if the contour is selected, ``0`` if it isn't. + +.. attribute:: box + +The bounding box for the contour. (read only) + +.. attribute:: clockwise + +Direction of contour: ``1=clockwise``, ``0=counterclockwise``. + +.. attribute:: points + +The contour as a list of :doc:`Point `\'s. + +.. attribute:: bPoints + +The contour as a list of :doc:`bPoint `\'s. + +Attribute examples +------------------ + +Examples with contours and points :doc:`here <../howtos/understanding_contours>`. + +Methods for segments +-------------------- + +For regular drawing in glyphs: please use :doc:`Pens <../howtos/use_pens>`. If you want to mess with segments on a lower level, be our guest: + +.. function:: appendSegment(segmentType, points, smooth=False) + +Add a segment to the contour. Parameters? + +.. function:: insertSegment(index, segmentType, points, smooth=False): + +Insert a segment into the contour. + +.. function:: removeSegment(index): + +Remove a segment from the contour. + +.. function:: setStartSegment(segmentIndex): + +Set the first node on the contour. + +Methods for points +------------------ + +.. function:: appendBPoint(pointType, anchor, bcpIn=(0, 0), bcpOut=(0, 0)) + +Append a ``bPoint`` to the contour. + +.. function:: autoStartSegment + +Automatically set the lower left point of the contour as the first point. + +.. function:: insertBPoint(index, pointType, anchor, bcpIn=(0, 0), bcpOut=(0, 0)) + +Insert a ``bPoint`` at index on the contour. + +Other methods +------------- + +.. function:: reverseContour() + +Reverse contour direction. + +.. function:: copy + +Duplicate this contour. + +.. function:: draw(aPen) + +Draw the object with a RoboFab segment pen. + +.. function:: drawPoints(aPen) + +Draw the object with a point pen. + +.. function:: move((x, y)) + +Move the contour. + +.. function:: pointInside((x, y), evenOdd=0) + +Determine if the point is inside or ouside of the contour. + +.. function:: round() + +Round the value of all points in the contour. + +.. function:: scale((x, y), center=(0, 0)) + +Scale the contour by ``x`` and ``y``. Optionally set the center of the scale. + +.. function:: rotate(angle, offset=None) + +Rotate the contour by ``angle`` (in degrees). Optionally set an ``offset`` value. + +.. function:: skew(angle, offset=None) + +Skew the contour by ``angle`` (in degrees). Optionally set an ``offset`` value. + +.. function:: transform(matrix) + +Transform this contour. Use a Transform matrix object to mess with the contour. See also :doc:`how to use transformations <../howtos/use_transformations>`. + +Method examples +--------------- + +.. code:: + + # robofab manual + # Contour object + # method examples diff --git a/_sources/objects/RFont.rst.txt b/_sources/objects/RFont.rst.txt new file mode 100644 index 0000000..545f279 --- /dev/null +++ b/_sources/objects/RFont.rst.txt @@ -0,0 +1,224 @@ +RFont +===== + +.. image:: ../../images/RFont.gif + +Usage +----- + +.. showcode:: ../../examples/objects/RFont_00.py + +Description +----------- + +Perhaps the first object you get to play with. The ``RFont`` object is the central part that connects all glyphs with font information (like names, key dimensions etc.). In FontLab the ``RFont`` object talks directly to the glyphs and font data in the FontLab font it belongs to. In UFO or NoneLab use, the ``RFont`` object contains the data and saves it to UFO. ``RFont`` object behave like dictionaries: the glyphname is the key and the returned value is a :doc:`RGlyph` object for that glyph. If the glyph does not exist ``RFont`` will raise an ``IndexError``. + +``RFont`` has a couple of important sub-objects which are worth checking out. The font's kerning is stored in a :doc:`RKerning` object and can be reached as an attribute at ``RFont.kerning``. Fontnames, key dimensions, flags etc are stored in a :doc:`RInfo` object which is available through ``RFont.info``. The ``RFont.lib`` is an :doc:`RLib ` object which behaves as a dictionary. + +Iterating +--------- + +One of the most important uses of the ``RFont`` object is that it makes it really easy to iterate ("step through") the glyphs in the font. + +.. showcode:: ../../examples/objects/RFont_01.py + +This makes the code clear and simple. + +FontLab / UFO +------------- + +All basic attributes, methods and behaviour for ``RFont`` objects created in FontLab or in NoneLab are identical. However, the ``RFont`` objects in FontLab have some additional attributes and methods that make special FontLab functionality available. These extra methods and attributes are listed seperately below. + +RFont Attributes +---------------- + +.. attribute:: path + +The path to the font (read only). + +.. attribute:: kerning + +The :doc:`RKerning` object. Cache the ``font.kerning`` object to optimise your script for speed: + +.. showcode:: ../../examples/objects/RFont_02.py + +.. attribute:: info + +The :doc:`RInfo` object with all the font's names and key dimensions. + +.. attribute:: lib + +The lib object which behaves like a dictionary for arbitrary data that needs to be stored with the font. In FontLab the lib is stored in the ``.vfb`` file. In UFO based fonts the lib is a separate ``.plist`` file. Have a look at how to use the lib. + +.. attribute:: fileName + +The filename and path of this font. + +.. attribute:: psHints + +A :doc:`PostScriptFontHintValues ` object with all font level PostScript hinting information, such as the blue values and stems. + +Attribute examples +------------------ + +.. showcode:: ../../examples/objects/RFont_03.py + +RFont Methods available in FontLab and UFO +------------------------------------------ + +.. function:: RFont[glyphName] + +Asking the font for a glyph by ``glyphName`` like a dictionary. + +.. function:: has_key(glyphName) + +Return ``True`` if ``glyphName`` is present in the font. + +.. function:: keys() + +Return a list of all glyph names in this font. + +.. function:: newGlyph(glyphName, clear=True) + +Create a new, empty glyph in the font with ``glyphName``. If clear is ``True`` (by default) this will clear the glyph if it already exists under this name. + +.. note:: ``clear=True`` is now default in both FontLab and NoneLab implementations. + +.. function:: removeGlyph(glyphName) + +Remove a glyph from the font. This method will show a slightly different behaviour in FontLab and pure Python. In FontLab, components that reference the glyph that is being removed will be decomposed. In plain Python, the components will continue to point to the glyph. + +.. function:: insertGlyph(aGlyph, name=None) + +Inserts ``aGlyph`` in the font, the new glyph object is returned. If the font already has a glyph with the same name the exisiting data is deleted. The optional as parameter is an alternative glyph name, to be used if you want to insert the glyph with a different name. + +.. note:: As of robofab svn version 200, the ``as`` argument in ``insertGlyph`` has changed to ``name``. Python2.6+ uses ``as`` as a keyword so it can no longer be used. + +.. function:: compileGlyph(glyphName, baseName, accentNames, adjustWidth=False, preflight=False, printErrors=True) + +Compile components into a new glyph using components and anchorpoints. + +``glyphName`` + The name of the glyph where it all needs to go. + +``baseName`` + The name of the base glyph. + +``accentNames`` + A list of ``accentName``, ``anchorName`` tuples: ``[('acute', 'top'), etc]``. + +.. function:: generateGlyph(glyphName, replace=True, preflight=False, printErrors=True) + +Generate a glyph and return it. Assembled from ``GlyphConstruction.txt``. + +``replace=True`` + The font will replace the glyph if there is already one with this name. + +``preflight=True`` + The font will attempt to generate the glyph without adding it to the font. + +Do this to find out if there are any problems to make this glyph. For instance missing glyphs or components could be a problem. See :doc:`building accents <../howtos/building_accents>`. + +.. function:: getReverseComponentMapping + +Get a reversed map of component references in the font:: + + { + 'A' : ['Aacute', 'Aring'] + 'acute' : ['Aacute'] + 'ring' : ['Aring'] + #etc. + } + +.. function:: save(destDir=None, doProgress=False, saveNow=False) + +Save the font. + +.. function:: autoUnicodes + +Using ``fontTools.agl``, assign Unicode lists to all glyphs in the font. + +.. function:: interpolate + +See :doc:`how to interpolate <../howtos/interpolate>` for a detailed description of the interpolate method in ``RFont``. + +.. function:: round + +Round all of the coordinates in all of the glyphs to whole integer numbers. For instance a point at ``(12.3, -10.99)`` becomes ``(12, -11)``. UFO based fonts can deal with floating point coordinates, but for use in FontLab everything needs to be rounded otherwise bad things happen. + +.. function:: update + +Call to FontLab to refresh the font. You call ``update()`` after doing lots of manipulating and editing. In UFO based ``RFont`` objects ``update()`` doesn't do anything, but it exists. + +.. function:: copy + +Returns a deep copy of the font, i.e. all glyphs and all associated data is duplicated. + +.. function:: getCharacterMapping + +Returns a dict of unicode values to glyph names. + +Method examples +--------------- + +.. showcode:: ../../examples/objects/RFont_04.py + +FontLab +------- + +The following attributes and methods are only available to RoboFab objects in FontLab as they're based on application specific features. + +RFont Methods only available in FontLab +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. function:: naked + +Return the wrapped fontlab font object itself. This can be useful if you want to set very specific values in the fontlab font that aren't wrapped or handled by RoboFab objects. + +.. function:: writeUFO(self, path=None, doProgress=False, glyphNameToFileNameFunc=None, doHints=False, doInfo=True, doKerning=True, doGroups=True, doLib=True, doFeatures=True, glyphs=None, formatVersion=2) + +Write the font to UFO at path. + +``doProgress=True`` + Gives you a progressbar if you want. + +``glyphNameToFileNameFunc`` + An optional callback for alternative naming schemes. See :doc:`How to use glyph naming schemes <../howtos/glifnames>`. + +The other flags are new in RoboFab 1.2 and give you detailed control of what should and should not be written to UFO. The ``formatVersion`` flag determines the format of the UFO, ``1`` for UFO1, ``2`` for UFO2. + +.. function:: close() + +Close the font object and the font window in FontLab. + +.. function:: appendHGuide() + +Append a horizontal guide. + +.. function:: appendVGuide() + +Append a vertical guide. + +.. function:: clearHGuides() + +Clear all horizontal guides. + +.. function:: clearVGuides() + +Clear all vertical guides. + +.. function:: generate(outputType, path=None) + +Call FontLab to generate fonts with these parameters and location. Have a look at :doc:`generate fonts <../howtos/generating_fonts>` for a more detailed description of this method and how to use it. + +RFont Attributes available in FontLab only +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. attribute:: selection + +A list of selected glyph names in the font window. + +Attribute examples +^^^^^^^^^^^^^^^^^^ + +.. showcode:: ../../examples/objects/RFont_05.py diff --git a/_sources/objects/RGlyph.rst.txt b/_sources/objects/RGlyph.rst.txt new file mode 100644 index 0000000..6a37f9d --- /dev/null +++ b/_sources/objects/RGlyph.rst.txt @@ -0,0 +1,257 @@ +RGlyph +====== + +.. image:: ../../images/RGlyph.gif + +Usage +----- + +.. showcode:: ../../examples/objects/RGlyph_00.py + +Description +----------- + +The ``RGlyph`` object represents a glyph, its parts and associated data. In FontLab ``RGlyph`` talks directly to a glyph in an open font. In NoneLab the ``RGlyph`` refers to data read from (and written to) a specific glif file in a UFO. ``RGlyph`` can be used as a list of ``RContour``. When ``RGlyph`` is obtained from a RoboFab font object (see examples), the font is the parent object of the glyph. + +Attributes +---------- + +.. attribute:: components + +A list of the :doc:`Components ` in this glyph. + +.. attribute:: anchors + +A list of the :doc:`Anchors ` in this glyph. + +.. attribute:: len(aGlyph) + +The number of contours. + +.. attribute:: aGlyph[index] + +Get the :doc:`Contour ` object at index. + +.. attribute:: width + +The horizontal advance width of the glyph. + +.. attribute:: leftMargin + +The left margin of the glyph. + +.. attribute:: rightMargin + +The right margin of the glyph. + +.. attribute:: name + +The glyph name. + +.. attribute:: unicode + +The unicode value for this glyph, integer. + +.. attribute:: note + +A place for a short string, a note about this glyph. + +.. attribute:: unicodes + +A list of unicodes value for this glyph. Not all applications and editors support multiple unicode values for a glyph. Assume that ``glyph.unicode == glyph.unicodes[0]``. + +.. attribute:: box + +The bounding box. The values are ``(xMin, yMin, xMax, yMax)``. Note: these values represent the actual measurements of the shape of the glyph. They're usually different from the rectangle described by ``glyph.width`` / ``font.info.unitsPerEm``. + +.. attribute:: + - * + +Math operators work on glyphs. + +.. seealso:: :doc:`how to glyphmath <../howtos/glyphmath>`. + +.. attribute:: lib + +The glyph's lib, an :doc:`RLib `. + +.. seealso:: :doc:`how to use the lib <../howtos/use_lib>`. + +.. attribute:: psHints + +A :doc:`PostScriptGlyphHintValues ` object with all glyph level PostScript hints, vertical and horizontal. + +Attribute examples +------------------ + +.. showcode:: ../../examples/objects/RGlyph_01.py + +.. code:: + + 230 + Adieresis + [123, 345] + 1000 + 4 + +Methods +------- + +.. function:: getParent() + +Return the parent of this glyph, the font object it belongs to. The method returns ``None`` if there is none. + +.. function:: appendComponent(glyphName, (offsetX=0, offsetY=0), (scaleX=1, scaleY=1)) + +Add a component to the glyph. Optional values for ``offset`` and ``scale``. + +.. function:: appendContour(aContour) + +Add a contour to the glyph. + +.. function:: removeComponent(componentObject) + +Remove a component from the glyph. + +.. function:: appendGlyph(aGlyph, (offsetX=0, offsetY=0)) + +Add a whole glyph. This adds all the contours, anchors and components to the glyph. + +.. function:: appendAnchor(name, position) + +Create a new anchor in this glyph with name at position. + +.. function:: removeAnchor(anchor) + +Remove this anchor from the glyph. This only works if the glyph does not have anchors with duplicate names in exactly the same location with the same mark. + +.. function:: autoUnicodes() + +Try to find unicode values for this glyph. This method tries to match the glyph name to a known value. + +.. function:: copy() + +Returns a deep copy of this glyph. That means that all parts of the glyph: contours, components, anchors etc. are duplicated. + +.. function:: correctDirection() + +Correct the direction of all contours in this glyphs. + +.. function:: autoContourOrder() + +Automatically order the contours based on (in this order): + +1. the point count of the contours +2. the segment count of the contours +3. the ``x`` value of the center of the contours +4. the ``y`` value of the center of the contours +5. the surface of the bounding box of the contours + +.. function:: pointInside((x, y)) + +Returns ``True`` if the point is inside the "black" area of the glyph or ``False`` if the point is inside the "white" area of the glyph. + +.. function:: draw(aPen) + +Get this glyph to draw itself with the pen on offer. + +.. function:: drawPoints(aPointsPen) + +Get this glyph to draw itself with the points pen on offer. For differences between ``Pen`` and ``PointsPen`` see here :doc:`Pens `. + +.. function:: getPen() + +Returns an appropriate ``Pen`` object to draw in this glyph. + +.. function:: getPointPen() + +Returns an appropriate ``PointPen`` object to draw in this glyph. + +.. function:: interpolate(factor, minGlyph, maxGlyph, suppressError=True, analyzeOnly=False) + +Make this glyph the interpolation between ``minGlyph`` and ``maxGlyph`` by factor. When ``suppressError`` is ``True`` (the default value) this method will not complain if the interpolation is not possible. When ``analyzeOnly`` is ``True`` (default is ``False``), this method will only analyze if the interpolation is possible and provide a report if something is wrong. + +.. seealso:: :doc:`how to interpolate <../howtos/interpolate>`. + +.. function:: isCompatible(anotherGlyph, report=True) + +Returns ``True`` if the glyph has a compatible point structure as ``anotherGlyph``. When report is ``True``, ``isCompatible`` also returns a report on what the problems could be. + +.. seealso:: :doc:`how to interpolate <../howtos/interpolate>`. + +.. function:: isEmpty() + +Returns ``True`` when the glyph does not contain any contours, components or anchors. + +.. function:: move(x, y), contours=True, components=True, anchors=True) + +Move a glyph's items that are flagged as ``True``. + +.. function:: scale((x, y), center=(0, 0)) + +Scale the glyph by `x` and `y`. Optionally set the center of the scale. + +.. function:: rotate(angle, offset=None) + +Rotate the glyph by ``angle`` (in degrees). Optionally set an ``offset`` value. + +.. function:: skew(angle, offset=None) + +Skew the glyph by ``angle`` (in degrees). Optionally set an ``offset`` value. + +.. function:: rasterize(cellSize=50, xMin=None, yMin=None, xMax=None, yMax=None) + +Slice the glyph into a grid based on the cell size. It returns a list of lists containing bool values that indicate the black (``True``) or white (``False``) value of that particular cell. These lists are arranged from top to bottom of the glyph and proceed from left to right. This is an expensive operation! + +Method examples +--------------- + +.. showcode:: ../../examples/objects/RGlyph_02.py + +FontLab +------- + +Methods +^^^^^^^ + +Glyph methods only available in FontLab. + +.. function:: removeOverlap + +Remove overlap in this glyph. + +.. function:: naked + +Return the wrapped FontLab glyph object itself. This can be useful if you want to set very specific values in the FontLab font that aren't wrapped or handled by RoboFab objects. + +.. function:: update + +Tell FontLab to update all references to this glyph. Call this after you've changed something in the glyph object and you want these changes to be seen in the application. If you're calling ``glyph.update()`` a lot, for instance in a loop, consider calling it only once after the loop is done. You can also call ``font.update()`` if you've changed several glyphs at once. Calling ``update()`` makes a script slower. + +.. function:: getVGuides + +Return a list of wrapped vertical guides in this ``RGlyph``. + +.. function:: getHGuides + +Return a list of wrapped horizontal guides in this ``RGlyph``. + +.. function:: appendVGuide(x) + +Add a vertical guide at ``x`` in this ``RGlyph``. + +.. function:: appendHGuide(y) + +Add a horizontal guide at ``y`` in this ``RGlyph``. + +.. function:: clearVGuides() + +Remove vertical guides from this ``RGlyph``. + +.. function:: clearHGuides() + +Remove horizontal guides from this ``RGlyph``. + +Useful +------ + +.. showcode:: ../../examples/objects/RGlyph_03.py diff --git a/_sources/objects/RInfo.rst.txt b/_sources/objects/RInfo.rst.txt new file mode 100644 index 0000000..c5b9fb2 --- /dev/null +++ b/_sources/objects/RInfo.rst.txt @@ -0,0 +1,32 @@ +RInfo +===== + +.. image:: ../../images/RInfo.gif + +Usage +----- + +.. showcode:: ../../examples/objects/RInfo_00.py + +.. code:: + + MyFont Regular + Huib van Krimpen + Jan van Krimpen + LTTR + 1000 + 307 + #etc. + +Description +----------- + +``RInfo`` contains all names, numbers, URL's, dimensions, values, etc. that would otherwise clutter up the font object. You don't have to create a ``RInfo`` object yourself, ``RFont`` makes one when it is created. In FontLab the ``RInfo`` data is tunneled to the appropriate places in the FontLab font. In UFO land the data ends up in ``info.plist``. In all implementations ``RInfo`` doesn't check the validity of the entries, it just provides storage or access to them. + +Complete list of attributes +--------------------------- + +RoboFab version 1.2 implements new ``RInfo`` objects with extended attributes. The old attributes still work, but print a deprecation warning when they're accessed. Scripts written with UFO1 attributes should work. The specification of UFO2 has its own site, `UnifiedFontObject.org`_. The ``objectsRF.RInfo`` object implements all attributes listed, the ``objectsFL`` implementation misses a couple as the fields are not supported in FontLab. Please have a look at the `overview of the UFO2 font.info attributes`_. + +.. _UnifiedFontObject.org: http://unifiedFontObject.org/ +.. _overview of the UFO2 font.info attributes: http://unifiedfontobject.org/versions/ufo2/fontinfo.html diff --git a/_sources/objects/RKerning.rst.txt b/_sources/objects/RKerning.rst.txt new file mode 100644 index 0000000..9f7a75b --- /dev/null +++ b/_sources/objects/RKerning.rst.txt @@ -0,0 +1,130 @@ +RKerning +======== + +.. image:: ../../images/RKerning.gif + +Usage +----- + +.. showcode:: ../../examples/objects/RKerning_00.py + +.. code:: + + < RKerning for Mailer-Regular > + -123 + None + [('X', 'emdash'), + ('K', 'v'), + ('two', 'perthousand'), + ('guilsinglleft', 'a'), + ... etc.] + +Description +----------- + +``RKerning`` is a dictionary of kerning values. ``RFont`` makes a ``RKerning`` object when it is created and makes available as ``aFont.kerning`` attribute. The keys are tuples of the glyphs listed by their names: ``('T', 'e')``, ``('V', 'A')`` etc. ``None`` is returned if the pair does not exist, rather than raising an ``IndexError``. The parent of a kerning object is usually a Font. + +Methods +------- + +.. function:: add(value) + +Add value to all kerning pairs. + +.. function:: asDict() + +Return the object as a plain dictionary. + +.. function:: clear() + +Clear all the kerning (why would you want to do that?). + +.. function:: combine(kerningDicts, overwriteExisting=True) + +Combine two or more kerning dictionaries. Overwrite exsisting duplicate pairs if ``overwriteExisting=True``. + +.. function:: eliminate(leftGlyphsToEliminate=None, rightGlyphsToEliminate=None, analyzeOnly=False) + +Eliminate pairs containing a left glyph that is in the ``leftGlyphsToEliminate`` list or a right glyph that is in the ``rightGlyphsToELiminate`` list. sideGlyphsToEliminate can be a string: ``'a'`` or list: ``['a', 'b']``. ``analyzeOnly`` will not remove pairs. it will return a count of all pairs that would be removed. + +.. function:: explodeClasses(leftClassDict=None, rightClassDict=None, analyzeOnly=False) + +Turn class kerns into real kerning pairs. Classes should be defined in dicts: ``{'O':['C', 'G', 'Q'], 'H':['B', 'D', 'E', 'F', 'I']}``. ``analyzeOnly`` will not remove pairs. it will return a count of all pairs that would be added. + +.. function:: get(aPair) + +Get a value. Return ``None`` if the pair does not exist. + +.. function:: getAverage + +Return average of all kerning pairs. + +.. function:: getExtremes + +Return the lowest and highest kerning values. + +.. function:: getLeft(glyphName) + +Return a list of kerns with ``glyphName`` as left character. + +.. function:: getRight(glyphName) + +Return a list of kerns with ``glyphName`` as right character. + +.. function:: has_key(pair) + +Returns True if it has the pair. + +.. function:: implodeClasses(leftClassDict=None, rightClassDict=None, analyzeOnly=False) + +Condense the number of kerning pairs by applying classes. This will eliminate all pairs containg the classed glyphs leaving pairs that contain the key glyphs behind. ``analyzeOnly`` will not remove pairs. It will return a count of all pairs that would be removed. + +.. function:: importAFM(path, clearExisting=True) + +Import kerning pairs from an AFM file. ``clearExisting=True`` will clear all exising kerning. + +.. function:: interpolate(sourceDictOne, sourceDictTwo, value, clearExisting=True) + +Interpolate the kerning between ``sourceDictOne`` and ``sourceDictTwo``. ``clearExisting`` will clear existing kerning first. + +.. function:: items + +Return a list of ``(pair, value)`` tuples. + +.. function:: keys + +Returns a lust of available pairs. + +.. function:: minimize(minimum=10) + +Eliminate pairs with value less than minimum. + +.. function:: occurrenceCount(glyphsToCount) + +Return a dict with glyphs as keys and the number of occurances of that glyph in the kerning pairs as the value ``glyphsToCount`` can be a string: ``'a'`` or list: ``['a', 'b']`` + +.. function:: remove(pair) + +Remove a kerning pair. + +.. function:: round(multiple=10) + +Round the kerning pair values to increments of multiple. + +.. function:: scale(value) + +Scale all kernng pairs by value. + +.. function:: swapNames(swapTable) + +Change glyph names in all kerning pairs based on ``swapTable``:: + + swapTable = {'BeforeName':'AfterName', } + +.. function:: update(kerningDict) + +Replace kerning data with the data in the given ``kerningDict``. + +.. function:: values() + +Return a list of kerning values. diff --git a/_sources/objects/RPoint.rst.txt b/_sources/objects/RPoint.rst.txt new file mode 100644 index 0000000..0c0cbfc --- /dev/null +++ b/_sources/objects/RPoint.rst.txt @@ -0,0 +1,74 @@ +RPoint +====== + +.. image:: ../../images/RPoint.gif + +Usage +----- + +.. showcode:: ../../examples/objects/RPoint_00.py + +.. code:: + + + +Description +----------- + +``RPoint`` is perhaps the smallest object in RoboFab objects. It represents one single point with a particular coordinate in a contour. It is used to access off-curve and on-curve points alike. It's cousin, :doc:`bPoint` also provides access to incoming and outgoing bcps. ``RPoint`` is exclusively only one single point. + +Understanding Contours and outlines +----------------------------------- + +The way outline data is organised in RoboFab, and how the various objects relate is described here: :doc:`understanding contours <../howtos/understanding_contours>`. + +Attributes +---------- + +.. attribute:: x + +The ``x`` coordinate of this point. + +.. attribute:: y + +The ``y`` coordinate of this point. + +.. attribute:: type + +The ``type`` of this point. + +.. attribute:: selected + +Boolean for selection state, i.e. ``True`` or ``False``. + +UFO only attributes +------------------- + +.. attribute:: name + +The name of the point (UFO only). + +Methods +------- + +.. function:: copy() + +Return a deepcopy of the object. + +.. function:: move((x, y)) + +Move the anchor of the ``bPoint`` to ``(x,y)``. The relative coordinates of the ``bcpIn`` and ``bcpOut`` will remain the same, which means that in fact, they move the same distance. + +.. function:: round() + +Round the coordinates to whole integers. + +.. function:: select(state=True) + +Select this point. + +.. function:: transform(matrix) + +Transform this point. Use a Transform matrix object to mess with the point. + +.. seealso:: :doc:`how to use transformations <../howtos/use_transformations>`. diff --git a/_sources/objects/RSegment.rst.txt b/_sources/objects/RSegment.rst.txt new file mode 100644 index 0000000..b49a03a --- /dev/null +++ b/_sources/objects/RSegment.rst.txt @@ -0,0 +1,85 @@ +RSegment +======== + +.. image:: ../../images/RSegment.gif + +Usage +----- + +.. showcode:: ../../examples/objects/RSegment_00.py + +.. code:: + + + + + + + +Description +----------- + +A Contour object is a list of segments. A segment is a list of points with some special attributes and methods. + +Understanding Contours and outlines +----------------------------------- + +The way outline data is organised in RoboFab, and how the various objects relate is described here: :doc:`understanding contours <../howtos/understanding_contours>`. + +Attributes +---------- + +.. attribute:: type + +Type of segment. + +.. attribute:: smooth + +``True`` if the segment is ``smooth``, ``False`` if not. + +.. attribute:: selected + +Returns ``True`` if the segment is selected, ``False`` if not. + +.. attribute:: points + +List of points in the segment. + +.. attribute:: onCurve + +Returns the oncurve point associated with the segment. + +.. attribute:: offCurve + +Returns a list of offcurve points associated with the segment. + +Attribute examples +------------------ + +.. showcode:: ../../examples/objects/RSegment_01.py + +Methods +------- + +.. function:: copy + +Return a deepcopy of the object. + +.. function:: move((x, y)) + +Move the anchor of the ``bPoint`` to ``(x,y)``. The relative coordinates of the ``bcpIn`` and ``bcpOut`` will remain the same, which means that in fact, they move the same distance. + +.. function:: round + +Round the coordinates to whole integers. + +.. function:: transform(matrix) + +Transform this point. Use a Transform matrix object to mess with the point. + +.. seealso:: :doc:`how to use transformations <../howtos/use_transformations>`. + +Method examples +--------------- + +.. showcode:: ../../examples/objects/RSegment_02.py diff --git a/_sources/objects/bPoint.rst.txt b/_sources/objects/bPoint.rst.txt new file mode 100644 index 0000000..19693b5 --- /dev/null +++ b/_sources/objects/bPoint.rst.txt @@ -0,0 +1,87 @@ +bPoint +====== + +.. image:: ../../images/bPoint.gif + +Usage +----- + +.. showcode:: ../../examples/objects/bPoint_00.py + +.. code:: + + + +Description +----------- + +The ``bPoint`` is a point object which mimics the old "Bezier Point" from RoboFog. It has attributes for ``bcpIn``, ``anchor``, ``bcpOut`` and ``type``. The coordinates in ``bcpIn`` and ``bcpOut`` are relative to the position of the anchor. For instance, if the ``bcpIn`` is 20 units to the left of the anchor, its coordinates would be ``(-20,0)``, regardless of the coordinates of the anchor itself. Also: ``bcpIn`` will be ``(0,0)`` when it is "on top of the anchor", i.e. when there is no ``bcp`` it will still have a value. The parent of a ``bPoint`` is usually a Contour. + +Understanding Contours and outlines +----------------------------------- + +The way outline data is organised in RoboFab, and how the various objects relate is described here: :doc:`understanding contours <../howtos/understanding_contours>` + +Attributes +---------- + +.. attribute:: anchor + +The ``(x, y)`` position of (oncurve) anchor. + +.. attribute:: bcpIn + +The ``(x, y)`` position of the incoming (offcurve) bezier control point. + +.. attribute:: bcpOut + +The ``(x, y)`` position of the outgoing (offcurve) bezier control point. + +.. attribute:: type + +The type of the ``bPoint``. Either ``corner`` or ``curve``. + +Attribute examples +------------------ + +.. showcode:: ../../examples/objects/bPoint_01.py + +.. code:: + + (0, -175) (611, 337) (0, 175) + (0, 0) (223, 641) (0, 0) + etc.. + +Methods +------- + +.. function:: copy + +Return a deepcopy of the object. + +.. function:: move((x, y)) + +Move the anchor of the ``bPoint`` to ``(x,y)``. The relative coordinates of the ``bcpIn`` and ``bcpOut`` will remain the same, which means that in fact, they move the same distance. + +.. function:: round + +Round the coordinates to whole integers. + +.. function:: select(state=True) + +Select this point. + +.. function:: transform(matrix) + +Transform this point. Use a Transform matrix object to mess with the point. + +.. seealso:: :doc:`how to use transformations <../howtos/use_transformations>`. + +Method examples +--------------- + +.. code:: + + >>> # robofab manual + >>> # bPoint object + >>> # method examples diff --git a/_sources/objects/index.rst.txt b/_sources/objects/index.rst.txt new file mode 100644 index 0000000..0a556ec --- /dev/null +++ b/_sources/objects/index.rst.txt @@ -0,0 +1,22 @@ +Objects +======= + +.. toctree:: + :maxdepth: 1 + + objects.rst + model.rst + RFont.rst + RInfo.rst + RGlyph.rst + RContour.rst + RPoint.rst + bPoint.rst + RSegment.rst + RAnchor.rst + RComponent.rst + RKerning.rst + pens.rst + libs.rst + psHints.rst + psHintsGlyph.rst diff --git a/_sources/objects/libs.rst.txt b/_sources/objects/libs.rst.txt new file mode 100644 index 0000000..2772a59 --- /dev/null +++ b/_sources/objects/libs.rst.txt @@ -0,0 +1,38 @@ +RLib +==== + +.. image:: ../../images/fontLib.gif + +Usage +----- + +.. showcode:: ../../examples/objects/RLib_00.py + +.. code:: + + < RLib for Salmiak-Regular > + ['org.robofog.ufoExport.date', + 'org.robofog.ufoExport.encoding.current', + 'org.robofog.ufoExport.font.italicOffset', + 'org.robofog.ufoExport.sourcePath'] + +Description +----------- + +``RFont`` and ``RGlyph`` objects get lib objects when they're created, so you don't have to explicxitly make one. Lib objects behave like normal dictionaries. + +Where is this data stored? +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In RoboFab 1.0 and FontLab 4.6.1, the lib is saved inside the (FontLab native attributes!) ``glyph.customdata`` and ``font.customdata`` in the ``.vfb`` file. + +.. note:: + + A bug in FontLab 4.6.1 prevents the ``glyph.lib`` from being used: when data is stored in this field, the font can no longer be edited. FontLab Studio 5 introduces a new attribute customdict which is exclusively for storing Python data. Early tests indicate that RoboFab storage of lib data can move to this attribute, but further testing and introduction of the MacOS version are needed before RoboFab's Lib support can move to it. In UFO based fonts the libs are stored as ``.plist`` in the UFO. Have a look at :doc:`how to use the lib <../howtos/use_lib>`. + +Methods +------- + +.. function:: keys() + +Return a list of the keys. Normal dictionary stuff. diff --git a/_sources/objects/model.rst.txt b/_sources/objects/model.rst.txt new file mode 100644 index 0000000..299c0d3 --- /dev/null +++ b/_sources/objects/model.rst.txt @@ -0,0 +1,6 @@ +RoboFab Object Model +==================== + +.. image:: ../../images/ObjectModel.svg + +`RFont `_ · `RInfo `_ · `RGlyph `_ · `RContour `_ · `RPoint `_ · `bPoint `_ · `RSegment `_ · `RAnchor `_ · `RComponent `_ · `RKerning `_ · `RLib `_ diff --git a/_sources/objects/objects.rst.txt b/_sources/objects/objects.rst.txt new file mode 100644 index 0000000..2c20657 --- /dev/null +++ b/_sources/objects/objects.rst.txt @@ -0,0 +1,56 @@ +Overview +======== + +Model +----- + +.. image:: ../../images/logo.gif + +Here is a :doc:`handy map ` of the RoboFab objects. + +RoboFab Unified Font Objects +---------------------------- + +- :doc:`Map `: The objects and their relations. +- :doc:`Pen objects `: About Pen objects. +- :doc:`PostScript Glyph Hints `: Glyph attribute, contains glyph level PostScript hint data. +- :doc:`RAnchor `: A connection point for Components. +- :doc:`RComponent `: Belongs to a Glyph, refers to other Glyphs. +- :doc:`RContour `: Belongs to a Glyph, contains Segments. +- :doc:`RFont `: Contains Glyphs, names, kerning, data. +- :doc:`RGlyph `: Belongs to a Font, contains contours, components etc. +- :doc:`RInfo `: Part of a Font, contains all names, dimensions. +- :doc:`RKerning `: Part of a Font, contains all kerning data. +- :doc:`RLib `: Part of a Font, contains all arbitrary data. +- :doc:`RPoint `: A point on a Contour. +- :doc:`RSegment `: A part of a Contour, a series of severall off and one oncurve Points. +- :doc:`bPoint `: A point on a Contour with attributes for ``bcpIn``, ``bcpOut`` and ``anchor``. +- :doc:`psHints `: Part of a Font, contains font level PostScript hinting data. + +Scope +----- + +Naming conventions in RoboFab +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Attributes and method names follow a couple of consistent rules which make it easier to remember what they're called. + +- Class names start with a capital: ``RGlyph``, ``BasePen`` etc. + +- Method and attribute names start with lowercase: ``glyph.center()``, ``glyph.width``. + +- Private attributes and methods start with underscore: ``point._index``. + +.. note:: Private methods and attributes are needed to make the objects work, but they're not intended for users to mess with, that's why they're called private. The description of the objects in this manual then do not list them. + +- All names follow ``camelCaseNaming`` as much as possible. So 'glyph name' becomes ``glyphName`` + +Availability of methods, attributes +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Unless noted otherwise, the examples, methods and attributes should work in all implementations of RoboFab, so within FontLab as well as NoneLab. These reference pages are written by an experienced RoboFab user, not a robot. All the objects have more attributes and methods than listed here. But these are the most important ones to get started with. For a full list refer to the **robofabDocs** in the RoboFab distribution. + +Perhaps not documented yet +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +As noted earlier, this documentation is written by a person, not a machine. So it is possible attributes, objects, methods are missing. Drop us a line if you're missing something. diff --git a/_sources/objects/pens.rst.txt b/_sources/objects/pens.rst.txt new file mode 100644 index 0000000..e6bd9c5 --- /dev/null +++ b/_sources/objects/pens.rst.txt @@ -0,0 +1,94 @@ +Pen objects +=========== + +Pens are very useful and powerful objects. The idea is this: a glyph contains drawing information like contours, components etc. There is a lot of code that wants to work with this drawing information. But rather than to give access to these contours directly, the glyph and pen work together. Each glyph has a ``draw()`` method which takes a pen as a parameter. The pen object has a couple of standard methods (along the lines of ``lineto``, ``moveto``, ``curveto`` etc.) which are called by the glyph in the right order and with the right coordinates. + +Abstraction +----------- + +Using the pen as an intermediate, the code that just wants to draw a glyph doesn't have to know the internal functions of the glyph, and in turn, the glyph doesn't have to learn anything about specific drawing environments. Different kinds of glyph object (for instance the ``objectsFL.RGlyph`` and the ``objectsRF.RGlyph``) work very different on the inside. One stores data in FontLab, the other stores the coordinates itself and writes to GLIF. But both ``RGlyph`` objects have a draw method which follows the same abstract drawing procedures. So the code that uses the ``RGlyph.draw(pen)`` is not aware of the difference between the two kinds of glyphs. + +Why pens? +^^^^^^^^^ + +In order to make a glyph draw in for instance a new graphics environment, you only need to write a new pen and implement the standard methods for the specifics of the environment. When that's done, all RoboFab glyphs can draw in the new world. But pens have also proven to be very useful as a means to get access to the outline data stored in a glyph without messing with the internal workings of a glyph. So even if you don't want to actually draw something on screen, the pen and ``draw()`` interface can help in for instance conversion, transformations, etc. One glyph can draw itself into another glyph as a way of copying itself while avoiding nasty dependencies, and circular references. + +Flavors of Pen +-------------- + +RoboFab has two different kinds of pen which do different things for different purposes and they're intended for different methods in Glyph. Have a look in robofab/pens/ to see different kinds of pen objects for different purposes. RoboFab already has a fair number of pens in stock, chances are you'll find something you need. Examples of Penmanship at the :doc:`How to use Pens <../howtos/use_pens>`. + +Pen() +^^^^^ + +The normal Pen object and pen that descend from it can be passed to ``aGlyph.draw(aPen)``. The Glyph calls these methods of the pen object to draw. It's very similar to "Drawing like PostScript". + +.. function:: moveTo(pt, smooth=False) + +Move the pen to the ``(x, y)`` in ``pt``. + +.. function:: lineTo(pt, smooth=False) + +Draw a straight line to the ``(x, y)`` coordinate in ``pt``. + +.. function:: curveTo(pt1, pt2, pt3, smooth=False) + +Draw a classic Cubic Bezier ("PostScript") curve through ``pt1`` (offcurve), ``pt2`` (also offcurve) and ``pt3`` which is oncurve again. + +.. function:: qCurveTo(*pts, **kwargs) + +Draw a Quadratic ("TrueType") curve through, well, any number of offcurve points. This is not the place to discuss Quadratic esoterics, but at least: this pen can deal with them and draw them. + +.. function:: closePath + +Tell the pen the path is finished. + +.. function:: addComponent(baseName, offset=(0, 0), scale=(1, 1)) + +Tell the pen to add a component of ``baseName``, at ``offset`` and with ``scale``. + +.. function:: addAnchor(name, (x, y)) + +Tell the pen to add an Anchor point with a name and a position. + +.. function:: setWidth(width) + +Tell the pen to set the width of the glyph. (deprecated) + +.. function:: setNote(note) + +Tell the pen to add a note to the glyph. (deprecated) + +.. function:: doneDrawing + +Tell the pen the drawing is done. + +PointsPen() +^^^^^^^^^^^ + +Where the normal pen is an easy tool to think about drawing, the ``PointsPen`` is geared towards accessing all the data in the contours of the glyph. A ``PointsPen`` has a very simple interface, it just steps through all the points in a Glyph. Too complicated if you just want your script to draw in a glyph somewhere, but very useful for conversions of one thing to another, and when you're dealing with more elaborate point structures like several consecutive offcurve points. Again, have a look in the robofab/pens to see the available pens. Also the `LettError wiki <#>`_ has an in-depth description of the pen protocols. The ``PointsPen`` is passed to the ``aGlyph.drawPoints(aPointsPen)`` + +.. function:: beginPath + +Start a new sub path. + +.. function:: endPath + +End the current sub path. + +.. function:: addPoint(pt, segmentType=None, smooth=False, name=None, **kwargs) + +Add a point to the current sub path. + +.. function:: addComponent(self, baseGlyphName, transformation) + +Add a sub glyph. + +Need a pen? +----------- + +If you need a pen to do some drawing in a ``Glyph`` object, you can ask the glyph to get you one. Depending on the environment you're in RoboFab will get you the right kind of pen object to do the drawing: + +.. showcode:: ../../examples/objects/pen_00.py + +See also a more in depth look at pens :doc:`here <../howtos/use_pens>`. diff --git a/_sources/objects/psHints.rst.txt b/_sources/objects/psHints.rst.txt new file mode 100644 index 0000000..2358b33 --- /dev/null +++ b/_sources/objects/psHints.rst.txt @@ -0,0 +1,162 @@ +PostScript font hint values +=========================== + +The ``font.psHints`` object, introduced in RoboFab 1.1.3 rev.89 showed it was useful to have access to the various PostScript blues values. But it also proved it was necessary to store them elsewhere. So in RoboFab 1.2 rev.172, the blues values found a permanent home in the new ``RInfo`` object. The ``font.psHints`` object is still functional, all fields are rerouted to their new places. The ``font.psHint`` attribute might be deprecated in the future. + +Note on accessing blues data in FontLab Studio +---------------------------------------------- + +A bug in FontLab's own Python attributes relating to blues, ``otherBlues``, ``familyBlues`` and ``familyOtherBlues`` fields, makes it impossible to set the full number of zones using Python. The actual number of zones which can be set from Python is one less than the number in the Adobe specification. A warning will be printed when a zone will be dropped. Using the FontLab font info dialog, all zones can be set. + +The font.info attributes (since RoboFab 1.2) +-------------------------------------------- + +.. attribute:: font.info.postscriptBlueValues + +(number list) A list of up to 14 integers or floats specifying the values that should be in the Type 1/CFF ``BlueValues`` field. This list must contain an even number of integers following the rules defined in the Type 1/CFF specification. + +.. attribute:: font.info.postscriptOtherBlues + +(number list) A list of up to 10 integers or floats specifying the values that should be in the Type 1/CFF ``OtherBlues`` field. This list must contain an even number of integers following the rules defined in the Type 1/CFF specification. + +.. attribute:: font.info.postscriptFamilyBlues + +(number list) A list of up to 14 integers or floats specifying the values that should be in the Type 1/CFF ``FamilyBlues`` field. This list must contain an even number of integers following the rules defined in the Type 1/CFF specification. + +.. attribute:: font.info.postscriptFamilyOtherBlues + +(number list) A list of up to 10 integers or floats specifying the values that should be in the Type 1/CFF ``FamilyOtherBlues`` field. This list must contain an even number of integers following the rules defined in the Type 1/CFF specification. + +.. attribute:: font.info.postscriptStemSnapH + +(number list) List of horizontal stems sorted in increasing order. Up to 12 integers or floats are possible. This corresponds to the Type 1/CFF ``StemSnapH`` field. + +.. attribute:: font.info.postscriptStemSnapV + +(number list) List of vertical stems sorted in increasing order. Up to 12 integers or floats are possible. This corresponds to the Type 1/CFF ``StemSnapV`` field. + +.. attribute:: font.info.postscriptBlueFuzz + +(integer or float) BlueFuzz value. This corresponds to the Type 1/CFF ``BlueFuzz`` field. + +.. attribute:: font.info.postscriptBlueShift + +(integer or float) BlueShift value. This corresponds to the Type 1/CFF ``BlueShift`` field. + +.. attribute:: font.info.postscriptBlueScale + +(float) BlueScale value. This corresponds to the Type 1/CFF ``BlueScale`` field. + +.. attribute:: font.info.postscriptForceBold + +(boolean) Indicates how the Type 1/CFF ``ForceBold`` field should be set. + +Example, some font.info blues attrs, usage +------------------------------------------ + +.. showcode:: ../../examples/objects/psHints_00.py + +.. code:: + + [-8, 0, 200, 208, 214, 114] + [-136, -128, -86, -84, 376, 386] + [-8, 0, 200, 208, 214, 224] + [-136, -128, -86, -84, 376, 386] + +Description of the font.psHint object +------------------------------------- + +``PostScriptFontHintValues`` is the class of the object found at ``font.psHints``. It has a couple of attributes of its own which give you access to the font level PostScript hinting information. For exact information on the meaning and usage of these values, please refer to the developer resources at `adobe.com`_. + +.. _adobe.com: + +The ``PostScriptFontHintValues`` objects, in FontLab and NoneLab flavor, can respond to ``add``, ``sub``, ``mul``, ``rmul``, ``div`` and ``rdiv``, so you can do math with them, for instance interpolations. Available since `ChangeSet 44`_. + +.. _ChangeSet 44: http://code.robofab.com/changeset/44 + +Example, the font.psHints object, usage +--------------------------------------- + +.. showcode:: ../../examples/objects/psHints_01.py + +.. code:: + + { 'forceBold': False, 'blueScale': 0.25, 'blueFuzz': 0, + 'blueShift': 4, 'hStems': [24, 50], 'vStems': [66, 4, 30, 72, 50], + 'blueValues': [[-8, 0], [200, 208], [214, 224]], + 'otherBlues': [[-136, -128], [-86, -84], [376, 386]], + 'familyOtherBlues': [[-136, -128], [-86, -84], [376, 386]], + 'familyBlues': [[-8, 0], [200, 208], [214, 224]], } + +.. showcode:: ../../examples/objects/psHints_02.py + +Attributes +---------- + +.. attribute:: blueShift + +Value for blue shift. Integer in FontLab, float or int in NoneLab. + +.. attribute:: blueScale + +Value for blue scale. Float in FontLab and NoneLab. + +.. attribute:: blueFuzz + +Value for blue fuzz. Integer in FontLab, float or int in NoneLab. + +.. attribute:: forceBold + +Value for force bold. Boolean in FontLab and NoneLab. + +.. attribute:: blueValues + +List of pairs of numbers indicating the primary alignment zones. Integers in FontLab, floats or ints in NoneLab. + +.. attribute:: otherBlues + +List of pairs of numbers indicating the secondary alignment zones. Integers in FontLab, floats or ints in NoneLab. + +.. attribute:: familyBlues + +List of pairs of numbers indicating the primary family alignment zones. Integers in FontLab, floats or ints in NoneLab. + +.. attribute:: familyOtherBlues + +List of pairs of numbers indicating the secondary family alignment zones. Integers in FontLab, floats or ints in NoneLab. + +.. attribute:: vStems + +List of numbers for the vertical stems. Integers in FontLab, floats or ints in NoneLab. + +.. attribute:: hStems + +List of numbers for the horizontal stems. Integers in FontLab, floats or ints in NoneLab. + +Methods +------- + +.. function:: copy + +Returns a copy of the object. Both in FontLab and NoneLab the copy will be an ``objectsRF.PostScriptFontHintValues``. + +.. function:: round + +Round the values to ints as much as the nature of the values allows. Note: ``blueScale`` is not rounded, it is a ``float``, ``forceBold`` is set to ``False`` if ``-0.5 < value < 0.5``. Otherwise it will be ``True``, ``blueShift``, ``blueFuzz`` are rounded to ``int``, stems are rounded to ``int``, blues are rounded to ``int``. + +.. function:: asDict + +Returns a dictionary with all attributes and values of this object. + +.. function:: fromDict(aDict) + +This will look for familiar attributes in ``aDict`` and assign the value to the object. + +.. function:: update(anotherPSHintsObject) + +This will copy values from the other object. + +Examples +-------- + +.. showcode:: ../../examples/objects/psHints_03.py diff --git a/_sources/objects/psHintsGlyph.rst.txt b/_sources/objects/psHintsGlyph.rst.txt new file mode 100644 index 0000000..fb28783 --- /dev/null +++ b/_sources/objects/psHintsGlyph.rst.txt @@ -0,0 +1,61 @@ +PostScript glyph hint values +============================ + +Usage +----- + +.. code:: + + # example of accessing the hint data. + # from robofab.world import CurrentFont + +Description +----------- + +``PostScriptGlyphHintValues`` is the class of the object found at ``aGlyph.psHints``. It has a couple of attributes of its own which give you access to the glyph level PostScript hint information. + +The ``PostScriptGlyphHintValues`` objects, in FontLab and NoneLab flavor, can respond to ``add``, ``sub``, ``mul``, ``rmul``, ``div`` and ``rdiv``, so you can do math with them, for instance interpolations. Available since `ChangeSet 44`_. + +.. _ChangeSet 44: http://code.robofab.com/changeset/44 + +Attributes +^^^^^^^^^^ + +.. attribute:: hHints + +List of (position, width) tuples for horizontal. + +.. attribute:: vHints + +List of (position, width) tuples. + +Methods +^^^^^^^ + +.. function:: copy() + +Returns a copy of the object. Both in FontLab and NoneLab the copy will be an ``objectsRF.PostScriptFontHintValues``. + +.. function:: round() + +Round the values to ints as much as the nature of the values allows. + +.. note:: + + - ``blueScale`` is not rounded, it is a float. + - ``forceBold`` is set to ``False`` if ``-0.5 < value < 0.5``. Otherwise it will be ``True``. + - ``blueShift``, ``blueFuzz`` are rounded to integers. + - ``stems`` are rounded to integers. + - ``blues`` are rounded to integers. + +.. function:: asDict() + +Returns a dictionary with all attributes and values of this object. + +.. function:: fromDict(aDict) + +Rhis will look for familiar attributes in ``aDict`` and assign the value to the object. + +.. function:: update(anotherPSHintsObject) + +This will copy values from the other object. diff --git a/_sources/talks/dialogkit.rst.txt b/_sources/talks/dialogkit.rst.txt new file mode 100644 index 0000000..228e334 --- /dev/null +++ b/_sources/talks/dialogkit.rst.txt @@ -0,0 +1,11 @@ +DialogKit +========= + +DialogKit is a Python library for creating GUI dialogs in FontLab and Mac OS X Cocoa applications that have a Python layer. + +The library implements a subset of the `Vanilla library`_, which in turn was inspired by Just van Rossum’s classic W library. In FontLab, dialogKit wraps the built-in GUI classes ``Dialog`` and ``Canvas`` and adds a few things along the way. The goal is to provide a simple API and consistent, or as consistent as possible, behavior between applications. + +`Download, documentation and examples on github`_. At the time of writing, the documentation is part of the download, but needs to be compiled into html. + +.. _Vanilla library: http://github.com/typesupply/vanilla +.. _Download, documentation and examples on github: http://github.com/typesupply/dialogKit diff --git a/_sources/talks/editors.rst.txt b/_sources/talks/editors.rst.txt new file mode 100644 index 0000000..5c4fbbc --- /dev/null +++ b/_sources/talks/editors.rst.txt @@ -0,0 +1,144 @@ +Python, RoboFab, FontLab, Editors +================================= + +Scripting? +---------- + +These talks are about scripting. The term *scripting* is loosely defined as "writing small programs" without making it sound as difficult or complicated as "programming". Scripting is programming of course, but you don't have to tell anyone. You're using a programming language, *Python*, to write a script (or whatever you want to call it), which is then acted out by the *Python interpreter*. This is a program which will try to follow your instructions, giving feedback when it runs into problems or finishing the job when it doesn't. Running into problems is not something to be afraid of, Python does it very politely with a *traceback*, Python's way of reporting what went wrong and roughly where it the code it happened. We'll see a lot of these and we'll learn how to read these reports and understand what went wrong. + +Why? +---- + +Scripting is not type design. Or perhaps better: scripting is everything but typedesign. Scripts won't help you find ideas or draw a better curve. But it might help you make simple tools for things you need to do often. Just like anything, it will get better with some experience, but even a badly written, simple script can save you lots of time. You don't have to be (or become) a professional programmer to make it a useful skill. + +Where +----- + +Python is a modern, open source, programming language which is relatively easy to work with. There are Pythons for all operating systems and it has many developers building many different tools for it. It is not just for fonts and glyphs, there are networking and scientific tools, games, web applications. Years ago *RoboFog* introduced Python to make tools for typedesign and the idea stuck. Now there is a range of type applications that use Python: FontLab, the Adobe FDK, MetricsMachine, RoboFab. Learning Python means you can use your skills in more than one application. + +There are several places where you can write your code. Each with their own purpose and use. We'll look at some of them: + +**FontLab's Macro panel** + A simple code editor in FontLab where you can edit and run scripts. The advantage is that you're in FontLab and can start work immediately, manipulating fonts and glyphs which are open. But the panel is lacking features which are useful when writing a lot of code, which is why FontLab includes the: + +**FontLab with "external editor"** + In the FontLab preferences panel you can select another application as your python editor of choice. So when you hit the Macros button, this editor will pop up. This requires that your script is saved in a file somewhere on disk. You can use the editor to write the code, but FontLab will still run the program. FontLab doesn't actually execute the Python code, but uses a system installed interpreter. + +**Python IDE, Win, Mac OSX** + There are several IDE ("Integrated Development Environment") programs for Python on Mac and Windows. This means basically a Python code editor which can also run your code. Some of them offer debugging tools, module browsers or even complete interface toolkits. These IDE's are general programming tools and don't know much about type specific things. More and more code editors offer Python execution, for instance in **BBEdit** and **Textmate** on OSX you can edit your code, hit a cmd key and have the code run in the OSX Python interpreter. This is similar to the FontLab-with-external-editor option. + +**Command-line Python interpreter** + A form of Python where you write a line of code at a prompt and it is immediately executed. Useful to test simple problems, but not for anything over a couple of lines of code. + +**Command-line Python** + Use the installed command-line Python interpreter to execute files. The interpreter is called with the filename as an argument:: + + >>> python myCode.py + ...does stuff... + +Objects +------- + +Perhaps the most useful invention in programming since the paper-punch card is called **object oriented programming**. The term is used to describe a way of programming in which the data you're working on, and the code which belongs to that data are kept together, much like a person holding a handful of balloons on strings, in a single *object*, the cluster of balloons. This may sound a bit abstract. But it's a way to keep all the code and data sorted in a useful way. Otherwise there will be too much stuff very quickly. More terminology: + +**attributes** + The things an object knows about, its data or value. An object's data is stored in its attributes. + +**methods** + The things an object can do. The code to manipulate an object, its functions. + +Risking an example: an object of the class *car* has an attribute *color* (blue) and a method *drive* (slow). Big objects are usually split up into smaller, more specific objects. For instance, a *Font* object offers access to *Glyph* objects. The way the various objects relate, wich object contains what etc. — the way something is abstracted — is called an *object model*. A map of the object model used in RoboFab is in :doc:`the Fab docs <../objects/model>`. An object model is also called *API* for Application Programming Interface. + +FontLab objects? RoboFab objects? Are there different flavors of objects? Doesn't that confuse things? FontLab has its own object model. There are FontLab Font objects and FontLab Glyph objects. But these objects are relatively low-level, that means that while using these objects, you have to keep track of a lot of things yourself and understand some FontLab peculiarities. This makes it difficult to write code efficiently. RoboFab is a layer of objects built on top of the FontLab objects, making it a lot easier to work with the data, fewer things to memorise and that means faster development. FontLab now comes bundled with RoboFab. In this conference we focus mainly on the RoboFab objects, but for some things the FontLab objects are needed. + +Back to Python. Objects, attributes and methods follow the **dot separated syntax** which is a handy way to clearly state what method or attribute you want to talk to. Other programming languages use dot syntax as well, for instance JavaScript or PHP. + +.. code:: + + # attribute + someObject.someAttribute + someObject.anotherAttribute + font.path + glyph.width + + # method + someObject.someMethod(aParameter) + someObject.anotherMethod() + font.generate() + glyph.clear() + +See how the dot connects the names? But this can go deeper than one level as well. Sometimes objects contain other objects, which in turn can have.. etc. Dont' worry about getting lost, this is why there is documentation. + +.. code:: + + # attribute + someObject.someOtherObject.theOtherObjectsAttribute + font.info.fullName + font.info.familyName + + # method + someObject.someOtherObject.theOtherObjectsMethod(aParameter) + font.kerning.update() + +Did you notice some lines has parentheses after them, and others don't? Writing `()` means you want to use the method and execute it. In Python terms: the **method** is **called**. + +.. code:: + + # a method but not called, you're looking at + # the python object which contains the method. + font.update + + # but calling a method is more useful, + # it means: take this code and run it. + font.update() + +Names of variables and methods +------------------------------ + +In Robofab we have a couple of conventions for naming classes, attributes, methods and functions. These make it easier to predict what something is called and that means fewer trips to the documentation. This is what we're talking about: + +**camelCase** + This means that when a name is made up from several words, eachAdditionalWordStartsWithACap. Examples: ``glyphName``, ``kernTable``, ``groupList``, ``fontTools``. + +**class names** + Always start with an uppercase, then camelCase. Examples: ``RFont``, ``RGlyph``, ``RKerning``. + +**attribute and method names** + Always start with a lowercase, then camelCase. Examples: ``kerning.importAFM()``, ``glyph.drawPoints()``. + +.. note:: + + These are our conventions, we do it this way because we prefer it. But that does not mean that Python requires it, as long as your names are legal Python you can write whatever you want. It's just useful to stick to a predictable method one way or the other. Please look at the standard `Python documentation`_ for a full description of the language. Some rules about legal Python names: + + .. _Python documentation: http://python.org/doc/ + + - Names can be arbitrarily long. + - Names can contain letters and numbers. + - The first character has to be a letter. + - Names can contain upper and lower case letters. + - Upper and lower case letters are different. + - ``bruce`` and ``Bruce`` are different variable names + - The underscore character ``_`` is legal. ex: ``my_name`` + +Installing RoboFab +------------------ + +Installing RoboFab is usually straightforward. There are quite a few combinations of operating system, FontLab version and Python version possible, some with their own pecularities. There's not much we can do about that, you just have to get it sorted. + +More :doc:`installation notes <../intro/install>` in the RoboFab documentation. + +Documentation +------------- + +There is a lot of documentation available on the internet. When writing code, `Google`_ is your best friend -- there is almost always someone else who has dealt with or written about the same problem. Reading the documentation is always a good idea. Looking at code snippets is useful too because it will explain how other people have solved problems. Even if a particular bit of code doesn't do what you're looking for, it can give you ideas. + +.. _Google: http://google.com + +- :doc:`RoboFab objects <../objects/objects>`: the RoboFab API and reference. +- `FontLab objects`_: the FontLab documentation. API and reference for the FontLab objects. +- :doc:`RoboFab introduction to Scripting <../howtos/scripting>`: RoboFab scripting intro. +- `How to think like a computer scientist`_: an introduction into learning Python. Not specifically about typedesign, but general Python programming, lists, dicts, variables, stuff like that. +- :doc:`Emergency Python Basics `: elsewhere on this site an short overview of some of Python's basic stuff. + +.. _FontLab objects: http://dev.fontlab.net/flpydoc/ +.. _How to think like a computer scientist: http://www.greenteapress.com/thinkpython/ diff --git a/_sources/talks/index.rst.txt b/_sources/talks/index.rst.txt new file mode 100644 index 0000000..6453d7d --- /dev/null +++ b/_sources/talks/index.rst.txt @@ -0,0 +1,41 @@ +Step-by-step +============ + +These are chapters about scripting in Python, where and how to make your code and how to use RoboFab objects. Illustrated with many examples. These documents started out as conference notes for the Robothon09 Conference. They have been updated for UFO2. + +.. toctree:: + :maxdepth: 1 + :hidden: + + editors.rst + python_basics.rst + session1.rst + session2.rst + session3.rst + interpolation.rst + session6.rst + session4.rst + dialogkit.rst + +Sections +-------- + +- :doc:`01: Editors `: Where to use RoboFab, where to edit. +- :doc:`02: Basic Python `: Some rules, syntax. +- :doc:`03: Font object, Info object `: Introduction to Font and Info objects, with examples. +- :doc:`04: Glyph object and Pen object `: Introduction to Glyph and Pen objects. +- :doc:`05: Kerning object and glyph building `: Introduction to the Kerning object, and a closer look at building glyphs from parts. +- :doc:`06: Interpolation `: Scripting for interpolation. +- :doc:`07: Production `: Scripting for production. +- :doc:`08: NoneLab `: Adventures in NoneLab, scripting outside the box. +- :doc:`09: Dialog Kit `: Interface toolkit for FontLab. + +Additional resources +-------------------- + +The `Unified Font Object Specification site`_ featuring the UFO 2 extension. + +Find dozens of useful packages at the `TypeSupply.com public code repository`_, for instance DialogKit, Defcon, UFO2FDK and many more. + +.. _Unified Font Object Specification site : http://unifiedfontobject.org/ +.. _TypeSupply.com public code repository : http://code.typesupply.com/ diff --git a/_sources/talks/interpolation.rst.txt b/_sources/talks/interpolation.rst.txt new file mode 100644 index 0000000..646f030 --- /dev/null +++ b/_sources/talks/interpolation.rst.txt @@ -0,0 +1,209 @@ +Scripting for interpolation +=========================== + +.. image:: ../../images/RGlyph.gif + +.. image:: ../../images/RFont.gif + +Interpolation +------------- + +In this session we're going to look at scripting and interpolation. Building an interpolation system has 2 phases: **preparing** it and **using** it. Though this isn't necessarily a design / production difference. In the first phase you need to make sure all the data is set up properly, the compatible glyphs in each master, matching contours in each glyph, path directions, start point locations etc. This can be a lot of work, but RoboFab can assist by reporting the problems. The second phase, using the interpolation comes when everything works and rather than look for problems (there shouldn't be any) you just want to generate all the weights as fast as possible and get on with it proofing and other things. + +Terminology +----------- + +The glyphs (or whole fonts) that are used in an interpolation system are usually called **masters**. The **interpolation** factor is a number between ``0`` and ``1``. With ``factor=0`` the result will be identical to the first master (in this case glyph ``A``), and as you can probably guess, with ``factor=1`` the result will match glyph ``B``. ``factor=0.5`` means the resulting shape will be exactly between the two masters. The factor can actually also be outside the ``0``, ``1`` range -- in that case we speak of **extrapolation**. The particular change in a glyph when interpolating from one master to another is called an **axis**. + +Why use RoboFab interpolation? +------------------------------ + +All the alternatives come with strings attached. FontLab's **Blend** tool forces points in contours which don't match. This is handy if you're looking for a quick fix, but it can more or less destroy your masters. Alternatively you can use the Multiple Master tools, but this requires all of your masters to be in the same file and drawing this way can be tricky. Since interpolation is a useful process in typedesign, and a good candidate for scripting we decided to include solid interpolation support in Robofab. + +Interpolating glyphs +-------------------- + +In the first example we're going to interpolate two glyphs in the same font. This can be useful in the design stage, for sketching or testing. The result is stored in a third glyph. Note: if you want to run this example in FontLab, open a new, empty font. Use the circle tool to draw one circle in ``A``, and again in ``B``. Make sure these are different enough to tell what's going on: + +.. showcode:: ../../examples/talks/interpol_00.py + +You see there are 3 glyphs involved: the two masters (``A`` and ``B``) and a new glyph which is used to store the results. In this case the new glyph is stored as ``C``, but it can be helpful to give it a more descriptive name. This is not very PostScript-like, but chances are these glyphs won't make it to production anyway, so it's not a problem. Notice that ``interpolate()`` is a method of the ``Glyph`` object. The ``Font`` object has an interpolate method as well, more about that later. The :doc:`obligatory link <../howtos/interpolate>` to the relevant RoboFab documentation. + +Here's the same script, but now it generates a range of interpolated glyphs, each with a better name which tells you which interpolation factor was used: + +.. showcode:: ../../examples/talks/interpol_01.py + +.. code:: + + interpolating result_0.000000 + interpolating result_0.100000 + interpolating result_0.200000 + interpolating result_0.300000 + interpolating result_0.400000 + interpolating result_0.500000 + interpolating result_0.600000 + interpolating result_0.700000 + interpolating result_0.800000 + interpolating result_0.900000 + +.. image:: ../../images/glyphinterpol.gif + +Here you see a range of resulting glyphs as they could be generated by the script above. + +Rounding errors +--------------- + +When you interpolate in FontLab you need to take into account that the results will be rounded off. Coordinates can only consist of whole numbers, i,e, ``101`` or ``102`` but not ``101.3290`` There is a nice solution for working with floating point precision glyphs using RoboFab. Here's a brief introduction: + +.. showcode:: ../../examples/talks/interpol_02.py + +.. code:: + + float glyph 285.07676 114.59806 + float glyph 641.51202 285.66048 + float glyph 452.009385 679.5407 + float glyph 95.96647 508.47828 + integer glyph 285 115 + integer glyph 642 286 + integer glyph 452 680 + integer glyph 96 508 + +Use ``font.insertGlyph(myOrphanFloatGlyph, name="someName")`` if you want to insert the glyph back into a real font. Inserting causes the glyph points to be rounded off again. In a similar way you can make a font object which does not refer to an open FontLab font. In such a font you can store intermediate floating point glyphs of interpolations. + +.. note:: + + The ``as`` parameter in ``insertGlyph`` changed to ``name`` as of RoboFab svn version 200. As of python 2.6 ``as`` is now a reserved keyword. + +Making it work +-------------- + +The following table shows the problems glyphs can have when interpolating. **Compatible** means that the data can interpolate. **Functioning** means that the result actually works as a glyph. You'll see there are several combinations where glyphs are compatible, but the interpolation is not functional. + ++--------------------------------------------------------+---------------------------------------+--------------------------------------+ +| masters | result | fix | ++========================================================+=======================================+======================================+ +| .. image:: ../../images/compatibility-scheme_2_01.gif | Compatible and functioning. Same | -- | +| | number of points, same direction, | | +| | same start point location. | | ++--------------------------------------------------------+---------------------------------------+--------------------------------------+ +| .. image:: ../../images/compatibility-scheme_2_02.gif | Unusual, but compatible and | -- | +| | functioning. The number of off-curve | | +| | points differ, but these are assumed | | +| | to be on top of the on-curve when | | +| | missing. Note: this only works for | | +| | segments with 2 off-curve points. | | ++--------------------------------------------------------+---------------------------------------+--------------------------------------+ +| .. image:: ../../images/compatibility-scheme_2_03.gif | Compatible and functioning. Same | -- | +| | number of points, same direction, | | +| | same start point location, same | | +| | contour order. | | ++--------------------------------------------------------+---------------------------------------+--------------------------------------+ +| .. image:: ../../images/compatibility-scheme_2_04.gif | Incompatible and not functioning: | Edit the masters. | +| | different number of points. | | ++--------------------------------------------------------+---------------------------------------+--------------------------------------+ +| .. image:: ../../images/compatibility-scheme_2_05.gif | Compatible but not functioning: | apply ``c.autoStartSegment()`` | +| | start point is in the wrong place. | on each contour, otherwise | +| | | edit the masters. | ++--------------------------------------------------------+---------------------------------------+--------------------------------------+ +| .. image:: ../../images/compatibility-scheme_2_06.gif | Incompatible and not functioning: | Edit the masters. | +| | different number of contours | | ++--------------------------------------------------------+---------------------------------------+--------------------------------------+ +| .. image:: ../../images/compatibility-scheme_2_07.gif | Compatible but not functioning: one | apply ``glyph.correctDirection()``, | +| | of the contours is turning in the | otherwise edit the masters. | +| | wrong direction. | | ++--------------------------------------------------------+---------------------------------------+--------------------------------------+ +| .. image:: ../../images/compatibility-scheme_2_08.gif | Compatible but not functioning. | apply ``glyph.autoContourOrder()``, | +| | Contour order: the paths are in the | otherwise edit the masters. | +| | wrong order. | | ++--------------------------------------------------------+---------------------------------------+--------------------------------------+ + +Here are some snippets which can help prepare your glyphs. Suppose your test font has two incompatible glyphs ``A`` and ``B``: + +.. showcode:: ../../examples/talks/interpol_03.py + +.. code:: + + False + +So, there's the answer in code, they can't interpolate. Suppose the glyphs were in fact compatible, the answer will read True. The ``isCompatible()`` method takes another parameter: + +.. showcode:: ../../examples/talks/interpol_04.py + +.. code:: + + (False, ["Fatal error: contour 1 in glyph A and glyph B don't have the same number of segments."]) + +Apart from the stunted grammar, this will tell you more or less what's wrong with the two glyphs. Now you have something to fix. Another frequently found error is this:: + + (False, ["Fatal error: glyph A and glyph B don't have the same number of contours."]) + +More subtle errors happen when one of the contours in one of the masters turns in the wrong direction, or the start point of the contour is in a different place. These won't trip incompatibility errors like ones above, you have to verify the results. + +The following example shows methods which can help to make glyph more compatible. These methods use rules to arrange the starting point, the order of the contours and the direction of the contours. It is likely, but not garanteed, that other masters of your interpolation will respond the same way to these rules. For instance, ``autoStartSegment()`` moves the starting point of a contour to the most, bottom left point on the contour. If all your masters share the same structure, this will make sense. But if the masters are radically different on purpose, these rules won't produce the right results and you have to prepare the glyphs manually: + +.. showcode:: ../../examples/talks/interpol_05.py + +Interpolating fonts +------------------- + +The following script interpolates two fonts and stores the results in a third. It also smoothly introduces a couple of simple user interface thingies: ``AskString`` and ``SelectFont``. Have a look at the :doc:`how to page on the simple dialogs stuff <../intro/dialogs>`. ``AskString()`` presents a small dialogbox with a prompt and a text input box. It will return the value you typed in, or None if you didn't. Which kinda implies you need to check whether the input makes sense before continuing, but that's a different project. ``SelectFont()`` gives you simple dialog with a list of the currently open fonts. When you select a font name, the object for that font is returned. If you don't select anything, ``None`` is returned: + +.. showcode:: ../../examples/talks/interpol_06.py + +This script asks you to select 2 fonts, then it asks you for an interpolation factor. Then is creates a new font (in FontLab a new empty font window will pop up). Then the ``font.interpolate()`` method of this new font is called with the interpolation factor you entered before, and the two fonts you selected. + +Interpolate Kerning +------------------- + +In the example above the kerning is interpolated separately, the Kerning object has its own ``interpolate()`` method. When a kernpair exists in both masters, the resulting pair will be the expected interpolated value. If a pair is missing from one, the interpolation will assume it has value ``0``. This only works for flat, non-class kerning. Interpolating class based kerning with exceptions requires more attention. Some Robofab developers have this working though. + +GlyphMath (aside 1) +------------------- + +If they're compatible, Robofab Glyph objects can be used in Python math expression: you can add, subtract, multiply and divide them like normal numbers or variables. The math is applied to the coordinates of each point in the glyph. The result of a glyphMath operation is a new glyph. You can then insert this glyph in a font, or use it for other math operations. + ++----------------------------------------------------+---------------------------------------------------------+ +| GlyphMath | operation | ++====================================================+=========================================================+ +| .. image:: ../../images/glyphmath_examples_01.gif | **addition**: the coordinates of each point are added | ++----------------------------------------------------+---------------------------------------------------------+ +| .. image:: ../../images/glyphmath_examples_02.gif | **subtraction**: the coordinates of each point are | +| | subtracted. Note that though the glyph looks | +| | unrecognisable, all points are still there. | +| | Literally the difference between the two glyphs. | ++----------------------------------------------------+---------------------------------------------------------+ +| .. image:: ../../images/glyphmath_examples_03.gif | **multiplication**: scaling the glyph up. When you | +| | multiply with a tuple like ``(1.3, 1.05)`` the first | +| | value is used to multiply the ``x`` coordinates, the | +| | second value is used for the ``y`` coordinates. | ++----------------------------------------------------+---------------------------------------------------------+ +| .. image:: ../../images/glyphmath_examples_04.gif | **division**: scaling the glyph down. When you divide | +| | with a tuple like ``(30, 29)`` the first value is used | +| | to divide the ``x`` coordinates, the second value is | +| | used for the ``y`` coordinates. | ++----------------------------------------------------+---------------------------------------------------------+ +| .. image:: ../../images/glyphmath_examples_05.gif | Combination of operations to make a real | +| | interpolation. | ++----------------------------------------------------+---------------------------------------------------------+ + +.. showcode:: ../../examples/talks/interpol_07.py + +You can use GlyphMath to create interpolation effects, transplant transformations from one glyph to another and superimpose several effects at once. + +Superpolation (aside 2) +----------------------- + +Shameless commercial: `Superpolator`_ is a tool for building complex interpolation systems. It's based on Robofab and doesn't really have a place in this presentation. It doesn't make complex interpolations easier, it makes them possible. But ask Erik afterwards. + +.. _Superpolator: http://superpolator.com/ + +Advanced Interpolation +---------------------- + +Here are two more advanced examples of interpolation. The first script asks for two master fonts. Then it will generate a list of weights with predefined names and factors. After interpolating, it will close the result font and continue with the next weight: + +.. showcode:: ../../examples/talks/interpol_08.py + +The next script is a bit tricky, but it can be useful tool in typedesign. Suppose you have a two interpolating masters of different weights. The script interpolates **in horizontal direction** with the heavy weight to increase the stem thickness of the glyph. Then it proceeds to horizontally scale the glyph in such a way that the increase of weight from the interpolation is reduced again. The effect of both operations is a condensed version of the original glyph, but with a comparable stem thickness as the original. If you measure the stems of both masters and enter the values in the script, it can calculate an exact match. Note that the success of this script depends on the quality of the interpolation, and how far you're pushing the limit. From a design point of view you might not even want the condensed to have the same stem thickness. This script won't produce ready-made condensed versions of your typeface, but it can be used to create a starting point for further editing: + +.. showcode:: ../../examples/talks/interpol_09.py diff --git a/_sources/talks/python_basics.rst.txt b/_sources/talks/python_basics.rst.txt new file mode 100644 index 0000000..ea84084 --- /dev/null +++ b/_sources/talks/python_basics.rst.txt @@ -0,0 +1,102 @@ +Basic Python +============ + +In these and following examples we'll be using a couple of programming things which are simple enough that, should you not be familiar with them, you might be able to figure out from the contect. While the experienced programmers will tap their feet impatiently for this to finish, and the newbies are struggling to pick their dicts from their strings: a very short overview of the stuff you're missing. + +Conditional statements +---------------------- + +If some condition is met: execute a separate block of your script:: + + >>> if 1+1 == 2: + ... print "still true" + >>> else: + ... print "oops" + still true + +Compound statements +------------------- + +For each item in this list: execute a seperate block of your script:: + + >>> for item in [1, 2, 3, "a"]: + ... print item + 1 + 2 + 3 + "a" + +Assignment +---------- + +This is basically setting something to a new value, or attaching a name to something:: + + >>> a = 10 + >>> print a + 10 + +The information that you want to work with in programming comes in different forms and colors: text, numbers, sequences of things. Python offers a nice range of tupperware boxes to stick them in. More things to keep track of, but: useful and these will be your friends. + +Strings +------- + +Text, letters, words, are called strings and they live between quotes. In order to allow quotes in strings you have several quote alternatives:: + + # examples of strings + a = "a string" + b = 'a string too' + c = 'a "string" too' + d = """a triple quoted string - but still just a string.""" + e = '''a triple quoted string - but still just a string.''' + +Numbers +------- + +Whole numbers, decimal numbers. You don't need to do anything special to make them, just write them:: + + # examples of numbers + a = 1900 + b = -239345 + c = 1.349683 + d = 0 + +Lists +----- + +Sequences can be written between brackets. You've seen one earlier. Lists are powerful things to keep stuff in order. Some objects can behave like lists. List objects have useful methods to manipulate them:: + + >>> # examples of lists + >>> aList = [4, "a", 2, 1] + >>> aListInAList = [ [1, 2], [3, 4] ] + >>> print len(aList) + >>> sort(aList) + >>> print aList + 4 + [1, 2, 4, 'a'] + +Dictionaries +------------ + +These are similar to lists, but rather than just store a sequence, a dictionary stores a ``key: value`` pair. In order to get the value, you need to provide the key. Dictionaries are written between {braces}. Some objects can behave like dictionaries. Dictionary objects have useful methods to manipulate them. While lists have their sequencential order, dictionaries don't, something to remember when you're iterating:: + + >>> # examples of dicts + >>> aDict = {"key": "value", 100: 200} + >>> print aDict.keys() + >>> print aDict.values() + >>> print aDict.items() + >>> print len(aDict) + [100, 'key'] + [200, 'value'] + [(100, 200), ('key', 'value')] + 2 + +Tuples +------ + +Sequences between parentheses, rather than square brackets. Tuples are very much like lists, except that you can't really change them. For instance a tuple can't sort like a list can:: + + # examples of tuples + aTuple = (1, 2, 3) + aTuple = ("a", "b", "c") + +And that's really all we're going to say about this. Figure out the rest yourself. diff --git a/_sources/talks/session1.rst.txt b/_sources/talks/session1.rst.txt new file mode 100644 index 0000000..c64e8b4 --- /dev/null +++ b/_sources/talks/session1.rst.txt @@ -0,0 +1,178 @@ +Font & Info objects +=================== + +.. image:: ../../images/RFont.gif + +Code! +----- + +So now then, you should have your editor fired up. Your RoboFab installed. Locate the output window as well:: + + import robofab.world + +If that runs without problems you're good to go. If a new window pops up with a traceback like this it means there's something wrong with the installation:: + + Traceback (most recent call last): + File "", line 1, in ? + ImportError: No module named robofab.world + +In this documentation, stuff in the output window is indicated with a tinted background. Whenever something is printed in Python code it will end up in the output window. + +Huh, import? +------------ + +Python can do a lot of different things. Some of its functionality is always available (the **built-in** things) but most of it is stored in separate **modules**. When you want to use code from a different module, you need to **import** it first so that Python knows it needs to look somewhere else for objects, functions and stuff. Most of the Robofab stuff is stored in the ``robofab.world`` module. Notice that dot there? The dot syntax also works for modules and modules within modules. If you want to import a module and Python can't find it, you will get a traceback with an ``ImportError``. You can also import specific things from another module, then you write:: + + from someModule import oneSpecificThing + from someModule.subModule import oneSpecificThing + from someModule import anotherSpecificThing, andAnotherThing + + # and these: + import someModule + import someModule.subModule + +We'll need to import a couple of useful functions from the robofab module to get started. To begin with, we'll look at ``CurrentFont`` and ``CurrentGlyph``. + +CurrentFont() +------------- + +So, suppose you have FontLab, and a font file open. Make sure it is a font you can trash if you have to, and not the single copy of the production master of your newest bestseller. How do you get started talking to that font in Python? Use ``CurrentFont()``. This is a special function which will return an object for the font which is at the front. When there are no fonts it will return ``None``: + +.. showcode:: ../../examples/talks/session1_00.py + +.. code:: + + + +A :doc:`Font <../objects/RFont>` object! We'll be using ``CurrentFont`` and that font object shortly, but first let's have a look at ``CurrentFont``'s siblings: ``CurrentGlyph`` and ``AllFonts``: + +.. showcode:: ../../examples/talks/session1_01.py + +.. code:: + + + +``CurrentGlyph()`` returns a :doc:`Glyph <../objects/RGlyph>` object for the glyph which is at the front. So this is a useful place to start if you want to write a script which manipulates a single glyph and you want an object for that glyph: + +.. showcode:: ../../examples/talks/session1_02.py + +.. code:: + + [, + , + ] + +``AllFonts()`` returns a list with Font objects, one object for each open font. ``CurrentFont``, ``CurrentGlyph`` and ``AllFonts`` are three very useful functions, and they all live in the ``robofab.world`` module. We'll be using them a lot. + +Some Font attributes +-------------------- + +So what are attributes of fonts objects? Let's have a look (at the documentation!): + +.. showcode:: ../../examples/talks/session1_03.py + +.. code:: + + /aFolder/anotherFolder/demoStuff/myFont.vfb + + + +Hang on! that didn't print anything that looks like kerning, and what's that ``font.info`` thing? Remember that objects can contain objects? The object model splits all font related data into smaller, easier to manage pieces. So a ``Font`` object has one single ``Info`` object which in turn stores all of the naming and dimensions. Same for ``font.kerning``, it's an object which represents all kerning data of the font. We'll get back to the :doc:`kerning object <../objects/RKerning>` later. + +Some Info attributes +-------------------- + +The Info object stores all of the :doc:`font's names, key dimensions <../objects/RInfo>` etc: + +.. showcode:: ../../examples/talks/session1_04.py + +.. code:: + + MyDemo + Plain + MyDemo Plain + 1000 + 720 + -280 + +Almost all attributes can also be set to new values. This is when it starts getting interesting. But it also opens new ways of messing your font up: + +.. showcode:: ../../examples/talks/session1_05.py + +.. code:: + + MyFamily + Roman + MyFamily-Roman + 600 + -400 + +A useful method of the Info object is ``autoNaming()``. It assumes you have entered correct data for ``familyName`` and ``styleName``. Based on these two values, a bunch of variations and permutations are generated and stored in the appropriate fields. These are the basic names, no fancy OpenType stuff: + +.. showcode:: ../../examples/talks/session1_06.py + +.. code:: + + myFamilyName myStyleName + myFamilyName-myStyleName + myFamilyName + +Getting to glyphs +----------------- + +We've seen ``CurrentGlyph`` and ``CurrentFont``, but how do you we get to other glyphs in a font? A ``Font`` object contains glyphs and this is what you do to get to them: + +.. showcode:: ../../examples/talks/session1_07.py + +.. code:: + + + + + + +The ``Font`` object in this case behaves like a Python dictionary object. Between the ``[`` square brackets ``]`` you can ask for a glyph by its (PostScript) name. In Python speak:: + + value = dictionary[key] + +If you want to look at all glyphs in a font, one at a time, you can loop or iterate through the font. It's written like this: + +.. showcode:: ../../examples/talks/session1_08.py + +.. code:: + + font has 201 glyphs + + + + + + + + ..etc.. + +A couple of things to look for in the example above: + +- ``len(font)`` shows Python's built-in ``len()`` function, which will try to count the thing its given and it will return the number. Fonts like to be counted and they respond with the number of glyphs. In this case the font has 201 glyphs. + +- All the glyphs are mixed up! there is no particular order! chaos! In Python dictionaries there is no standard order in which the keys appear. It will iterate through all the glyphs though. + +- Notice the indentation at the beginning of the line under ``for glyph in font``: This is Python's way of showing that all of the code that's indented belongs to the same loop. When the code is *dedented* again that's where Python will continue when it is done with the loop. + +When you want to be sure about the order in which the glyphs are looked at, you need to sort them first. Example: + +.. showcode:: ../../examples/talks/session1_09.py + +.. code:: + + font has 201 glyphs + + + + + + + + + + ..etc.. diff --git a/_sources/talks/session2.rst.txt b/_sources/talks/session2.rst.txt new file mode 100644 index 0000000..f821ef2 --- /dev/null +++ b/_sources/talks/session2.rst.txt @@ -0,0 +1,199 @@ +Glyph, Contour & Pen +==================== + +.. image:: ../../images/RGlyph.gif + +Working with :doc:`Glyph <../objects/RGlyph>`, :doc:`Contour <../objects/RContour>`, :doc:`Pen <../objects/pens>` objects. Deep in the font live the glyphs. Inside the glyphs are contours, components. Inside a contour are segments and points! + +Some Glyph attributes +--------------------- + +In the previous talk we saw ways of getting fonts and glyph objects. Now we're going to see what ``Glyph`` objects can do for us. Glyphs are perhaps the most interesting object in the whole API. Some basic attributes of a glyph object: + +.. showcode:: ../../examples/talks/session2_00.py + +.. code:: + + A + 812 + 0 + 0 + (0, 0, 812, 600) + 65 + +Some of these attributes can also be set, you can put new values in them. Why not all of them? For instance, the bounding box of a glyph is an attribute, it is useful information. But it depends entirely on the size of the contours in the glyph. There's no way in which you could set this attribute other than by changing the actual paths. Useful attributes you *can* set are things like the width, left and right margin: + +.. showcode:: ../../examples/talks/session2_01.py + +.. code:: + + 200 + 50 + 50 + 666 + +Notice the ``glyph.update()`` statement at the end. After setting the attributes to new values, the glyph data will be changed. But the FontLab interface will not have noticed your changes. For instance, the little preview in the font window might still show the old version. The ``update()`` method of the glyph object is a wakeup call for the application to refresh all glyph drawings with the new data. Note that it is just the **representation** that's being updated. The data itself was changed when the script was executed. Saving the file and opening it again will have the same effect in this respect. + +Have a look at the RoboFab documentation on the :doc:`Glyph <../objects/RGlyph>` object for more attributes and methods. + +Some Glyph methods +------------------ + +.. showcode:: ../../examples/talks/session2_02.py + +.. note:: + + These will really screw up your glyph if you don't want it to be moved 100 units horizontally and 75 units vertically, then scaled 50% horizontally and 150% vertically. Then the glyph ``B`` is added, the overlap is removed, the path directions are corrected and finally the app is told something was changed. + +getParent() +----------- + +The Glyph object has a ``glyph.getParent()`` method. When called it will return the **Font** object the glyph belongs to. If it has one: "orphan" glyphs are objects which don't belong to any particular font like the result of a GlyphMath operation or glyph level interpolation. When there is no parent, ``getParent()`` returns ``None``. You need to test for this result: + +.. showcode:: ../../examples/talks/session2_03.py + +.. code:: + + + +The stuff glyphs are made of +---------------------------- + +A glyph consists of contours, which in turn consist of points, right? If only it were that easy. There are all sorts of points conspiring to become all sorts of shapes. Bezier curves, Quadratic curves, open, closed, components. Sometimes it is just the point of view that's different. The :doc:`Understanding Contours and Segments <../howtos/understanding_contours>` section of the RoboFab documentation has a couple of diagrams of the different ways of looking at the vectors in a glyph. Let's have a look at :doc:`Contour <../objects/RContour>` objects first: + +.. showcode:: ../../examples/talks/session2_04.py + +.. code:: + + glyph has 2 contours + + + +So a ``Glyph`` object contains zero, one or more ``Contour`` objects. Let's see what secrets a ``Contour`` has: + +.. showcode:: ../../examples/talks/session2_05.py + +.. code:: + + [, + , + ... + ] + [, + , + ... + ] + [, + , + ... + ] + +Let's have a look at these different attributes. In the end, they're all describing the same shape, the same actual points. It's just sorted in different ways for different purposes. + +**contour.points** + This is a list of all points on a contour. off-curve and on-curve points are presented as ``RPoint`` objects. Each ``RPoint`` has ``x``, ``y``, ``type`` and ``smooth`` attributes. On-cuve and off-curve points are treated as equals. + +**contour.segments** + A segment is an object which represents a series of off-curve points and finally one on-curve point. Though kind of abstract, segments are needed to deal with quadratic curves which can have several off-curves on a row. + +**contour.bPoints** + bPoints are objects which look more or less like the curve points you know from editing Beziers. One main on-curve point and two satellite off-curve points or *bcps*: an incoming one and an outgoing one. This is more or less the kind of point that was used in RoboFog code. + +Again, please refer to the :doc:`Understanding Contours and Segments <../howtos/understanding_contours>` to make sense of these things visually. + +Finally, when you iterate through the ``contour.points``, you get to see :doc:`RPoint <../objects/RPoint>` objects with familiar things like ``x``, ``y``, and ``type`` attributes: + +.. showcode:: ../../examples/talks/session2_06.py + +.. code:: + + 37 509 move + 37 407 offcurve + 119 325 offcurve + 221 325 curve + 323 325 offcurve + 405 407 offcurve + 405 509 curve + 405 611 offcurve + 323 693 offcurve + 221 693 curve + 119 693 offcurve + 37 611 offcurve + 37 509 curve + +That looks interesting! Finally we're dealing with the stuff that letters are made of. You can now find the coordinates of every single point in the font, and change them if you want. But it looks very cumbersome to actually add shapes like this, all these contour objects, point objects. That's going to hurt, no? Yes. So, if you want to draw new forms there is a solution. + +The Pen and Draw model +---------------------- + +The pen/draw model is a very powerful concept, but it might seem a bit abstract to begin with. If you're interested in building filters, shape manipulating scripts, or programmatically draw glyphs, this is good to study. Otherwise, if you're here for the first time, just remember that there are ways to get paths into glyphs and that this is where you saw the examples for later reference. + +Glyph objects have a ``draw()`` method which takes a ``Pen`` object as a parameter. All glyphs know how to draw and all pen objects have the same methods (see below). When ``draw()`` is called, the glyph instructs the pen to recreate the shapes using ``moveTo()``, ``lineTo()``, ``curveTo()`` commands. The ``pen``/``draw()`` model is a standardised way of getting to the point data in a glyph. It is also a standardised way of getting data into a glyph. The glyph doesn't have to know what the pen is doing with its information and the pen doesn't have to know where the glyph gets its data from. That's how we like things in the object-oriented world. + +There is a wide range of pen objects available for different things. Some pens just print the coordinates of a glyph. Some pens draw contours in a glyph, some manipulate the data, others can draw on screen under certain conditions. + +How to get a pen object? A bunch of them are stored in the ``robofab.pens`` module, have a look in the source! But one of the first things you'll want to use a pen for is to construct paths in a glyph. A ``Glyph`` object has a ``glyph.getPen()`` method which will return the right Pen object for drawing in that glyph. Example: + +.. showcode:: ../../examples/talks/session2_07.py + +.. code:: + + + +The next example will show the use of a Pen object which doesn't construct any path, but rather it prints the instructions the glyph is calling to draw itself. Note: the stuff printed out by ``PrintingSegmentPen`` is Python code too. You can use this snippet to convert a shape into Python code, if for whatever reason you want to draw stuff programmatically. That's how the previous example was created: draw a shape in a glyph, print the draw instructions, write the rest of the code: + +.. showcode:: ../../examples/talks/session2_08.py + +.. code:: + + pen.moveTo((37, 509)) + pen.curveTo((37, 407), (119, 325), (221, 325)) + pen.curveTo((323, 325), (405, 407), (405, 509)) + pen.curveTo((405, 611), (323, 693), (221, 693)) + pen.curveTo((119, 693), (37, 611), (37, 509)) + pen.closePath() + +The following example uses a ``Pen`` to draw boxes as a simple rasteriser. Perhaps a bit overboard, but it illustrates what you can do with pens and creating paths in RoboFab: + +.. showcode:: ../../examples/talks/session2_09.py + +This is what it looks like. + +.. image:: ../../images/rasteriser.gif + +A more in-depth discussion of the Pen protocol, more examples of using pens, and some samples using pens to filter letterforms in the :doc:`RoboFab docs `. + +Another kind of pen +------------------- + +Well, it wouldn't be Python if there weren't at least two ways of doing things. The ``pen``/``draw()`` model draws on-curve points and only accepts off-curves as part of the ``curveTo()`` and ``qCurveTo()`` methods, there's no room for additional information. For instance a ``smooth`` flag or a name for a point (and there are good reasons to want to do that). That's where ``glyph.drawPoints()`` comes in handy. This method is similar to ``glyph.draw()`` but it takes a different pen, a ``PointPen``. All points are drawn one by one. ``PointPen`` objects are useful when you want to exactly address all information of each point in a shape. Compare the output of this example with the previous one. It's the same shape. Chances are you won't need ``PointPen`` for some time, but if you start working with pens it is good to know they exist: + +.. showcode:: ../../examples/talks/session2_10.py + +.. code:: + + pen.beginPath() + pen.addPoint((37, 509), segmentType='curve', smooth=True) + pen.addPoint((37, 407), **{'selected': False}) + pen.addPoint((119, 325), **{'selected': False}) + pen.addPoint((221, 325), segmentType='curve', smooth=True, **{'selected': 0}) + pen.addPoint((323, 325), **{'selected': False}) + pen.addPoint((405, 407), **{'selected': False}) + pen.addPoint((405, 509), segmentType='curve', smooth=True, **{'selected': 0}) + pen.addPoint((405, 611), **{'selected': False}) + pen.addPoint((323, 693), **{'selected': False}) + pen.addPoint((221, 693), segmentType='curve', smooth=True, **{'selected': 0}) + pen.addPoint((119, 693), **{'selected': False}) + pen.addPoint((37, 611), **{'selected': False}) + pen.endPath() + +Notice that a ``PointPen`` only has three methods: ``addPoint``, ``beginPath`` and ``endPath``. + +Path manipulation +----------------- + +FontLab has path manipulation tools which let you remove overlap and add and subtract shapes. Remove overlap is available: ``glyph.removeOverlap()``. Here is an example using the FontLab layer to subtract one shape from another to produce a third: + +.. showcode:: ../../examples/talks/session2_11.py + +This example also sneakily introduces the ``naked()`` method of the glyph object. This method returns FontLab's own object for the glyph. We'll look at this in a bit more detail later on. diff --git a/_sources/talks/session3.rst.txt b/_sources/talks/session3.rst.txt new file mode 100644 index 0000000..4b14703 --- /dev/null +++ b/_sources/talks/session3.rst.txt @@ -0,0 +1,110 @@ +Kerning and building Glyphs +=========================== + +.. image:: ../../images/RKerning.gif + +The Kerning object +------------------ + +All kerning data of a font is represented by the ``Kerning`` object. This object behaves like a Python dictionary: the key is a tuple of two glyph or groupnames, the dictionary value is the kern distance. + +In FontLab, ``font.kerning`` should not be called repeatedly like a normal attribute. Nothing will go wrong if you do, it will just be slow. The reason for this is that ``font.kerning`` is an attribute which (under the hood) has to do a lot of work to collect the data from the underlying FontLab file. Kerning in FontLab is stored at the glyph level, so to pull it up to the RoboFab level a massive iteration must occur when the kerning object is created. This happens each time you ask for the ``font.kerning`` attribute. But there's a simple way to work with that efficiently: cache the kerning object. Like so: + +.. showcode:: ../../examples/talks/session3_00.py + +.. code:: + + + 3141 + [('F', 'L'), ('D', 'G'), ('N', 'Eacute'), ..etc.. ] + +The Kerning object has some useful methods to transform and analyse the data: + +.. showcode:: ../../examples/talks/session3_01.py + +.. code:: + + + -20.5953517988 + {'a': 82, 'b': 52} + (-191, 184) + font has 3141 kerning pairs + ('F', 'L') -7 + ('D', 'G') 31 + ('N', 'Eacute') -34 + ('agrave.sc', 'z') -7 + ('K', 'v') -111 + ('Z', 'N') -15 + ..etc.. + +In the example above you see the ``Kerning`` object as attribute of a font object, then it is cached by storing it in a new variable. ``len(kerning)`` gives you the length of the kerning dictionary, the number of kern pairs. Have a look at the attributes and methods of the :doc:`Kerning object here <../objects/RKerning>`. It has some very useful methods for interpolating, sorting, combining and splitting kern tables. Back to the example, did you note that the kern pairs appear in random order? It's that Python dictionary thing again: keys of a dictionary have no particular order. Just like the example of the glyph names in a font object: + +.. showcode:: ../../examples/talks/session3_02.py + +.. code:: + + K v -111 + N Atilde -114 + W o -118 + W odieresis -118 + Acircumflex Y -103 + T e -153 + T adieresis -126 + T odieresis -133 + T aacute -126 + W eacute -141 + ..etc.. + +Another example of iterating through the kerning dictionary. This time each kern is tested if the value is less than ``-100``, and only when this is the case the pair is printed. This shows you how you can write code which responds to particular kinds of kerns: + +.. showcode:: ../../examples/talks/session3_03.py + +.. code:: + + acircumflex k -7 + acircumflex v -38 + acircumflex r -4 + acircumflex u -4 + acircumflex y -31 + acircumflex j -26 + ..etc.. + +This script prints all kerns with ``acircumflex`` as first glyph. + +Building glyphs +--------------- + +.. image:: ../../images/RAnchor.gif + +.. image:: ../../images/RComponent.gif + +A particularly interesting topic of scripting is building glyphs out of component parts. If a font already has all the parts, a script can, in many cases, assemble the accented versions. An overview of :doc:`glyph building options is in the how-to section of the Robofab docs <../howtos/building_accents>`. The first example takes a look at all necessary ingredients: making a new glyph, adding parts and finishing it. Then we'll look at more efficient ways: + +.. showcode:: ../../examples/talks/session3_04.py + +Let's have a look at that line by line. ``f.newGlyph("aacute")``. The ``newGlyph()`` of the ``RFont`` object creates a new glyph and names it ``aacute``. Then we can get to the new glyph by asking the font. The ``Glyph`` object has a ``appendComponent()`` method, which takes a ``glyphName`` of the glyph you want to add as a component and optionally an offset coordinate. This you can see in the line where the ``acute`` glyph is added. Then the width of the new glyph is set to the width of the original glyph. Finally FontLab is told to update. + +Well, that's going to be an awful lot of code if you have to write 4 lines of code for each new letter. There are other ways of going about this, using FontLab's ``Anchor`` points. + +glyph.generateGlyph() +--------------------- + +RoboFab has a database of glyph constructions based on the Adobe Glyph List. Have a look in your RoboFab code folder, ``robofab/Data/GlyphConstruction.txt``. The RoboFab list contains information about where components should be connected and what the anchor points are called:: + + Acircumflexdotaccent: A circumflex.top dotaccent.bottom + +This entry shows that ``Acircumflexdotaccent`` is constructed with components from ``A``, a ``circumflex`` using the ``top`` anchor, and ``dotaccent`` using the ``bottom`` anchor. In order to make this work, you need to add anchor points to your glyphs and accents. Check the FontLab manual for instructions. For instance the ``a`` has an anchor point named ``top``, the ``acute`` glyph has one named ``_top``:: + + # building a glyph from parts + from robofab.world import CurrentFont + f = CurrentFont() + font.generateGlyph("aacute") + +This creates a new glyph at ``aacute``, it puts all the components in the right place and sets the width. + +glyph.compileGlyph() +-------------------- + +Suppose you want to create glyphs using anchor points, but the glyphs don't have entries in Robofab's ``GlyphConstruction.txt`` list. What to do? Editing ``GlyphConstruction.txt`` is not recommended because you will loose your changes when you install a new version of RoboFab. ``Glyph`` has another method: ``compileGlyph()``. This method, like ``generateGlyph``, builds a new glyph with components, but you get to provide the list and tell which anchor points you want to use. ``compileGlyph`` takes a list of accents and anchors. It will follow the list and allow "stacking" of accents: + +.. showcode:: ../../examples/talks/session3_05.py diff --git a/_sources/talks/session4.rst.txt b/_sources/talks/session4.rst.txt new file mode 100644 index 0000000..fc949e9 --- /dev/null +++ b/_sources/talks/session4.rst.txt @@ -0,0 +1,103 @@ +Adventures in NoneLab, scripting outside the box +================================================ + +Working with text sources UFO, and GLIFs. FontLab export and import of UFO. Processing UFOs outside FontLab. + +UFO +--- + +Scripting a font editor without the font editor? RoboFab can export and import to the text based `UFO format`_ for font sources. You can export a FontLab font to ``.ufo``, and you can import a ``.ufo`` to FontLab easily. Read the :doc:`how-to <../howtos/makeufo>`. UFO export and import scripts are available from the RoboFab Scripts menu. But what do you do with ufos then? + +.. _UFO format: http://unifiedfontobject.org/ + +Scripting with fonts outside FontLab +------------------------------------ + +The nice thing about UFO is that RoboFab can read the files even when it is not running in FontLab. The Python interpreter that you use for FontLab, can run RoboFab scripts and apply them to font and glyphs stored in a UFO rather than a ``.vfb``. That opens possibilities for batch processing, storage in databases or version management systems, archiving or connecting your own tools to your workflow. FontLab specific functionality, such as generating font binaries, and complex path manipulations are not available in the **NoneLab** RoboFab, but you can make fonts, create and move glyphs, generate and manipulate kerning. We've taken great care to make sure that RoboFab based scripts work in both worlds. + +NoneLab +------- + +NoneLab is a word we coined to describe RoboFab/Python environments outside FontLab. Let's have a look at main the differences. + ++---------------------------+-----------------------------+-----------------------------------------------------------+ +| | FontLab | NoneLab | ++===========================+=============================+===========================================================+ +| Font binary generation | All formats. Import, | Read, write UFO. Read TT, OTF, PS T1 (through | +| | export UFO. | ``fontTools``). Experimental support for SVG fonts. | ++---------------------------+-----------------------------+-----------------------------------------------------------+ +| ``CurrentFont``, | Yes. | No. Use ``OpenFont(aPathToUFO)`` instead, or open the | +| ``CurrentGlyph``, | | ``.ufo`` fonts with ``RFont(aPathToUFO)``. | +| ``AllFonts`` | | | ++---------------------------+-----------------------------+-----------------------------------------------------------+ +| Interpolation | Yes. | Yes -- quite a bit faster too. | ++---------------------------+-----------------------------+-----------------------------------------------------------+ +| Make new fonts, move | Yes. | Yes. | +| glyphs, merge, split | | | +| files | | | ++---------------------------+-----------------------------+-----------------------------------------------------------+ +| Build accented glyphs | Yes. | Yes. | ++---------------------------+-----------------------------+-----------------------------------------------------------+ +| Manipulate kerning | Yes. | Yes. | ++---------------------------+-----------------------------+-----------------------------------------------------------+ +| Remove overlap | Yes. | No. | ++---------------------------+-----------------------------+-----------------------------------------------------------+ +| API | All RoboFab objects. | All RoboFab objects. | +| | Plus the underlying | | +| | FontLab objects. | | ++---------------------------+-----------------------------+-----------------------------------------------------------+ +| Platform | Mac OSX, Windows, | All platforms which support Python, Mac OSX, Windows, | +| | within FontLab | Linux, Unix. | ++---------------------------+-----------------------------+-----------------------------------------------------------+ +| Open file format | No, ``.vfb`` is a | Yes. UFO and GLIF formats are XML based, open and | +| | proprietary, binary | documented. You can build your own tools and use | +| | file format. | these formats. | ++---------------------------+-----------------------------+-----------------------------------------------------------+ +| Widgets, UI toolkit | DialogKit, plus the | When run as a window-less user in OSX or linux the | +| | set of basic windows | interface things are disabled. In some Python IDE's: | +| | from ``robofab.interface``. | the set of basic windows from ``robofab.interface``. | +| | | On OSX: Vanilla. | ++---------------------------+-----------------------------+-----------------------------------------------------------+ + +The UFO +------- + +A UFO is not really a single file, but rather a whole folder full of stuff with a ``.ufo`` extension in the name. So you can open up a ``.ufo`` and have a look inside. Some data is stored in ``.plist`` format. This is a flavor of XML and contains kerning, lib and font info. The glyphs are stored level deeper, in the glyphs folder. + +.. image:: ../../images/ufo.jpg + +The ``MyFont.ufo/glyphs/`` folder contains a list of ``.glif`` files and a single ``contents.plist`` file. This is the table of contents for the folder, it contains a table of glyph name to file name mappings. So when you start working with a ``.ufo`` and you want a particular glyph, RoboFab can find it faster. + +The GLIF +-------- + +GLyph Interchange Format, a readable XML based file with all data for a single glyph: width, unicode value, all contours, points and components. The ``glyph.lib`` is also stored here. + +.. image:: ../../images/cent.gif + +These screenshots are taken on an OSX machine, but the data is platform independent. Basically you can take any text editor and mess around with the points. While this is not a very efficient way to design type, it shows that the data is still there, accessible forever. + +Exporting UFO +------------- + +In the FontLab scripts folder that is distributed with RoboFab, you will find a set of scripts for importing and exporting UFO and GLIF. Open a test font and run this script from the Macro menu. It will generate a ``.ufo`` in the same folder as the source font file. + +.. image:: ../../images/exportmenu.gif + +FontLab Remote +-------------- + +If you happen to be using FontLab in Mac, you can use the FontLab Remote module to make FontLab receive Python instructions and data by **AppleEvents**. You need to start the AppleEvent handler by importing the ``robofab.tools.remote`` module. After importing it, FontLab can receive instructions by AppleEvent. You need to call remote once after starting FontLab. Now external scripts running outside FontLab can call the FontLab application, send it glyphs, get results back:: + + # start the AppleEvent handler + import robofab.tools.remote + FontLabRemote is on. + +The following script needs to be run in a python IDE. It will ask FontLab for its current glyph, and then it will store this glyph in a new font object outside FontLab. + +.. showcode:: ../../examples/talks/nonelab_00.py + +.. code:: + + + ['parenright'] diff --git a/_sources/talks/session6.rst.txt b/_sources/talks/session6.rst.txt new file mode 100644 index 0000000..24ceefd --- /dev/null +++ b/_sources/talks/session6.rst.txt @@ -0,0 +1,138 @@ +Scripting for production +======================== + +Production +---------- + +In the production phase of a font it all comes together: moving stuff around, naming, interpolations, quality control, generating, database work, it pays to invest some time (or money) in some really good scripts. Each foundry and designer has their own preferred ways of doing things. It's impossible to describe one production process and please everyone. So instead we're going to look at some of the things you probably have to do anyway. You will have to match and adapt for your own methods. + +Production scripts can save a lot of time. But be careful: it is costly to make mistakes with your production sources. Make sure to *test* production scripts first on duplicate data, preferably in a different folder. Doing something "quickly" to a massive kerning table only to discover it was your only copy, and the action was wrong -- will not save you any time. Like carpentry: measure twice, cut once. + +Batch processing +---------------- + +Here are some examples of applying changes to several fonts at once using ``AllFonts()``. Keep in mind that this applies to all fonts you have open in FontLab. So make sure to close any fonts that you don't want treated this way before running the script: + +.. showcode:: ../../examples/talks/session6_00.py + +Obviously you can extend these to do lots more: + +.. showcode:: ../../examples/talks/session6_01.py + +This is a more complex script. It iterates through all open fonts, collects some data in each and finally asks for a place to save all the data in a text file: + +.. showcode:: ../../examples/talks/session6_02.py + +This asks for a folder, then proceeds to save all open fonts in this folder: + +.. showcode:: ../../examples/talks/session6_03.py + +Here you can pick two fonts from the open fonts. The script will create a new, third font, and make interpolations with the interpolation factors in the ``values = [.3, .6]`` list. The interpolated font is then saved in the same folder as the first master. + +This touches on a slippery problem which can cause a lot of confusion. Robofab can only tell FontLab fonts apart from their path attribute, the place where each font is saved. A newly created font has not been saved yet, so it has no path. The effect is that when you have more than one new, unsaved font open, Robofab can't tell them apart (for a couple of reasons) and will continue to work with the first one. It will look like nothing is happening when you run a script. The way around this is to make sure you save each font you created with a script before creating another one. This is safer anyway. + +Here are some useful bits for batch processing fonts which are not open, but in a file. This script is a way to make python collect all files of a particular kind in a folder or folders within that folder. You can use the ``walker`` function outside of this script too, it's a useful thing to know: + +.. showcode:: ../../examples/talks/session6_04.py + +.. code:: + + ['/Applications/FontLab/Samples/FREESANS.VFB', '/Applications/FontLab/Samples/FREESERF.VFB'] + +Moving stuff around +------------------- + +The moving, merging and splitting of fonts. The first example moves selected glyphs in the same font and renames them. Note that if you remove the line ``f.removeGlyph(g.name)`` the same script effectively **copies** the glyphs. Also new in this script: it iterates through the whole font and checks for each glyph if the ``g.selected`` attribute is ``1`` or ``0``. If it is ``0``, the glyph is not selected in the font window. If it is ``1``, is is selected. It then proceeds to create a new glyph name, and calls ``f.insertGlyph()`` method which takes a glyph as parameter. The optional parameter ``name`` is to be able to insert the glyph under a different name. If you don't pass a parameter for ``name``, the font will insert the glyph under its own name. The glyph can come from the same font, or a different font, or be an orphan glyph: + +.. showcode:: ../../examples/talks/session6_05.py + +.. code:: + + moving A to A.sc + moving C to C.sc + moving B to B.sc + +Generating font binaries +------------------------ + +.. showcode:: ../../examples/talks/session6_06.py + +This will generate CFF flavored OpenType fonts for all open files. + +.. showcode:: ../../examples/talks/session6_07.py + +The script above generates fonts too, but is a bit more robust. FontLab sometimes crashes when it has to generate a long list of fonts and they're all open at the same time. This script asks you for a folder of ``.vfb`` sources (which in itself can be a useful ingredient for your own scripts). Then it will open them one by one and generate the fonts in the flavor indicated in the line ``f.generate('mactype1', dstDir)``. A list of types and their names can be found in the robofab documentation how-to page on generating fonts. This script also creates a new folder to store the generated fonts in, sorted by type. + +Merging +------- + +Here's a script, quite complex, for combining two fonts into one. Maybe not for the newbie, but if you're into it try to figure out how it works. It uses a couple of new concepts, like ``Sets`` and ``DigestPens``. If it is too complicated: don't worry: + +.. showcode:: ../../examples/talks/session6_08.py + +Dealing with Robofab limitations +-------------------------------- + +A handful of FontLab's own glyph and font methods are not supported in RoboFab. The reasons for this vary, some of them are very FontLab specific (for instance ``fl.productnumber`` or ``fl.username``), but most of the missing stuff was just not needed very often -- the following examples show how to get access to all functionality and attributes in the FontLab layer. + +FontLab layer +------------- + +To get to the FontLab layer, Robofab's Font and Glyph objects have a ``naked()`` method which returns the FontLab object. Note that you can still use the Robofab functionality like ``CurrentFont``, ``CurrentGlyph``, pens etc. The FontLab layer is documented here_. Maybe you remember the ``naked()`` method from the cookie cutter example: + +.. showcode:: ../../examples/talks/session6_09.py + +.. code:: + + + + +.. _here: http://dev.fontlab.net/flpydoc/view_html.html + +Other things you need to dig deeper for. Note that some of these objects appear to be broken. + +PostScript hints +^^^^^^^^^^^^^^^^ + +The vertical and horizontal hint zones as well as blue values can be read and set: + +.. showcode:: ../../examples/talks/session6_10.py + +.. code:: + + [,] + +All name fields +^^^^^^^^^^^^^^^ + +The FontLab table of OpenType names, the naming record, is available. See also the `FontLab reference for NameRecord`_: + +.. showcode:: ../../examples/talks/session6_11.py + +.. code:: + + 256 1 0 0 Bold + 256 3 1 1033 Bold + +.. _FontLab reference for NameRecord: http://dev.fontlab.net/flpydoc/html/NameRecord.xml.html + +Encodings +^^^^^^^^^ + +The FontLab ``Encoding`` object. See also the `FontLab reference for Encoding`_: + +.. showcode:: ../../examples/talks/session6_12.py + +.. code:: + + + ... + eacute 233 + ecircumflex 234 + edieresis 235 + igrave 236 + iacute 237 + icircumflex 238 + ..etc.. + +.. _FontLab reference for Encoding: http://dev.fontlab.net/flpydoc/html/Encoding.xml.html diff --git a/_static/_img/drawmodel.jpg b/_static/_img/drawmodel.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1f073a6f0be48cea83920a8fe3b9e785c34edf0b GIT binary patch literal 6228 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 YBFzklGW5nr5C1oe@qf9*W^3So03Ur&1ONa4 literal 0 HcmV?d00001 diff --git a/_static/_img/drawmodel_header.jpg b/_static/_img/drawmodel_header.jpg new file mode 100644 index 0000000000000000000000000000000000000000..6eca9d271c674e8be647875370129ad80ae74d0a GIT binary patch literal 8410 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 literal 0 HcmV?d00001 diff --git a/_static/_img/logo.gif b/_static/_img/logo.gif new file mode 100644 index 0000000000000000000000000000000000000000..91428d5ec654044a289e0c830181457e8a8a0342 GIT binary patch literal 3406 zcmXAoi#wDF!^WREK65shVKBo?1`}eKFpkZEan?Alb3;r+vJ#<`VZu1>C~b7wA*b4e zYNKSEA!SR2{c2^~OsJ%d}{z_j%8^hP38P*9QJDQVvxA<;9q1cP} zZEkKpPI1_4j~fGl``w7RNKLL*3H^j_qvu?KhqoxHQ2+rnFB6y>kd|>RdX<*cOf68~?eYZ=*aL(8tB63TsB^#K)QAS45*U!u)v*Kgj&wpdx zTwveL&bye$4P+q=a4?RP^V+?MhJ}g6;!Zd8yqU5-%m0f)^s<1Plam9-VmBpZQq9QL zThXug2VC<{kT(CPoI-!HF5W2fxY6sfpuM-d_juyorgmpW+h!-Z4~Cj`5ltGxOpt*VUn)tC<8m_GX&vOS^`UhL&O; zde5z?!5ljaBGl2&>a)smqgfiSoq6e#sCrb#MG*Yc^z4%gLZ!GNQuJ5t7q*K!dcO;b= zCJ(jd{y=FSZ${#fIEI-81+Cl5n=9q@isXYyu7gn)R4CCFj?*W3D}*c~JMK`9xgM$S$3%4bi`UM6j1jJ+zg0hLY0Y z9(b0Xe(3IjZC;xPGt7Mp1?SD(c!jdGSRQ8^SqgB%hNfqHjy;Q2liaolgRFyNSW%(d zA`%@|27QeUz{E)Yf1LmSFh0ZoZ`l8r|NR6HwE;j-)PP>KR)I1!c;*c9<&{JjYgq;2 z^vWrm%x7axDWq@DTPvx75p8UJd42n$l2_4_V32z6w8@9so*>X;>3>n9!gD^XGGzOc zR#{E7AiQx!tzRwVG_{IcVES6Tk>?dD4uB&}Ad-=4n%Ol(wa5;C5;)e{{rfd*wFEbj z1y&3eepqrL)4QMCqIeg!7W zq^7W;10R#^Okt?yc2)U%-ALueYhV-bI9o?4371JaDUKP2Ii}$~36buUekhb}a4*uQM8o?aYD%savb}d%@L6 zP@&wl#h6;GFIRMClKp@SI-U@@Ff~CS`0+l7&8sk1;{e=34t&d1YJ-q~UZsa)-re|q zm?Y3l&1#66R5Z+8YpOBaOJD3Q-P_yO9b;d}zQ@>O-?C!anumk1vTIv;XOMixQ&#qX zmUk~Qq@@QMzV(*|^uDoyb}(Gt(7d}K_gqamIs2%e5fM(5^al(!fjA~b2(4oJh6+43 zDJ1|7#q9pL-%-h)Q`)3YPvQ?mMJO1ug3@b@+iSXdoRp<`^8{Wb$9hKB5M3TenQZ_d zF5%OUL`oB7YW~G-Nel1?W+g{xPH>61vvACWxbH=1ST-&Fo z?!}mNGu@3Ctko9l`9&J=KkQ3`1WzXO*FR^d#c;oXKhqjYhrM$hNpeb~cuw=-(T{5A z>JNqdi~LFC3WR-dDSs4v7;=$C8TpHkfxdo!8N2=(yi((VX-pOaLN4(7Yh&VeF~FaG z{Pk={Q+ZKwCDDkb!A^RXL&=NsH|1rRy&M|<`6%FTpQ`^5Rd$?02djMfIf$00X0XyBe&K$(<*7LeqZ@>m3%~v1<&kH;136yG>W_+7Qq$h`(w~(Uxi+ zl#Sh%xD;`nTY4UO8G&F9BcfTY`Wz=eD^oVaqYy#38zAy$(t%QsF+8^g_2?f7-VDVj zzha%t81KU{l%slyDpZ6o!@G8-!nT?>Cb+~S>$%J8j^0s_+@1ZzGKNGA(B9Yw$C<1t z*5H4&F#`he>bBp8j!y6$Hal5rS%S+B?zAXYDe|%S*wvdmyW`_|kwc#8e6?!RwKin} z3ZkHLa_|6ikC00#IY4ouMCb4d9nxp4Qq==RB-% z%`;!*30#i;ZEScm#Uu_eop4<#&CiNB@c^yyV77&;59x?Cu#7{6?2F;@xpv2V1xd8h zm49Ki1FV8Nc(7r-g)Nz!CJ5C-UJLYMJ0BDg=z_moj~FQ{T70KKeB7?AV9iWvw+qoe3GD?(k4LPPQxeO^lfD``PwvQI==9hQgp z0A~^;JK+(Jc#UR0oXD2EBR7RC2ei`ZbzYC(d943 zl_~*^2MjZBHzu@r=^z<8U&WFL@nwkOMCkH6)2flb`}*i$F(Y?(Y#Ovb=Y%sg8%tSl zm)q|6yur3zgV*){irzS6;;51FjQJQOhpQQN{Js)q#CiE!;|QtX&V54Igu*M}BN8() zVqO8%N9N5N3f05ru`69zGZlooyh7XmY~JE69lREMNhDb~o5p6C`6}}-UTMHpcT|qo z!(X{-=_dXRI;J4M78J>b-LiGlW6w3FpBACks+g)Gl-!2qR1;TRO3331&;}D)82lg| zwTSDw8gP=h_4mmewJ{v7s>Wu@+L)?_)#*(%yQmVlZ9$HZ=0)Fv-(Qgrg(su06uzHY zNRa+KA9m}jw;7>PIBTsN=|m+jLqbLnzB>4DhRygl{|x_eeGLJg?i)W$lCt#s$)>bn3o; zb+hsovuRPMVejEZAuU^LU)|@@+9s!>pvPAsU9(Y{^YQo)C;v?pKIAme{DD|QINfar_MwG8?ZbLWIVy=0~G~@ zO?16=vfyC^sHVdbe(8E7edo$8-*2{FZ(MEZsLr z$GS>jD|GB-BEG5-eAjOXjN&acC{hF_GZs^;MhmYHu1%B)BRF-roD=*V=5&;WIKu2W zB8FSMPoGgNW3;mgp`bGE1*EdKQo&`!*%47CN+mjl7fHv&snJH@Ce4>2F*}t?2n6u_H#vJpF#rGn literal 0 HcmV?d00001 diff --git a/_static/_img/offdrawmodel_02.gif b/_static/_img/offdrawmodel_02.gif new file mode 100644 index 0000000000000000000000000000000000000000..cfa5e3f9a89818fea8a48819b655c7dc8f93dc5b GIT binary patch literal 1945 zcmdUsi#wG00)T(>ec#M543pfgjG2+4p&26LobxqGgiJVXM9o@Bl8}R*>ggLy#%+um zQaUvztYxnGPoc7N+?_cn~&$}Z$G$8P+93TYq zC`jtu3jnzJ_G&hM7{_rtFI(xr$&2HatE;QqONG)W63vg7lJ6u|4Hut$l!Kz^p?l(t zu7lqDc*;@PwO6%9qmjvE9=eyTQmOQMJ*LZNFc_?Du3K_8=k;dpRz-dJZOqLdzvYV7 zlg-FkSy^VbW>+Sv34$oopAn12zMo0;J=vFkajZ5Q&u|WOQYaK6k?7h)LrY7`#E0h? zhH0lds)j1wEx(IU?pVWO{OxqGesQ2@7AJn0TKawIv*&03|6g2xLr4IifcIy@pHBdF z6+;V)ilt{uWTj>06_xTTMfJJ!%9`2>br&zyqwdI6RfEb#s#d#SZdTeLz5+`pQd|42 zj@zA`o|c@eH@XTP`~;p_H*&x3$-tnV?51tI>%rGNRJ!wRJIEWYoK0PTVPz2|%N`9!IW;1=1+bk-cUSO-(m_^3ivgpo!);xsplWDq;+5ssFvYoJ-CR5DtR zB_c2tk$n-~mJ&{*Gf`Bg=oX$0;smtUs9Ar3T6cy4fm}kOaXcdVDv4W<1le7en2^&g zX`-IBiqvLNOX8i<^|8{ew$vO8q5Lv|&qd^hK4UGRj2ousqgUP2FtNopYCb7hPrU0` zK&s6g3j!jv{MT5xgvQSX(h`%|E%)nc3fD@y3=|$Cu=~5|Vb#zHG#hONw1fQ;ts^0c zif~9iZLnCL5g*ELG5PioQ^KRfkX_@MPCtbuY-xg)T*!&XfHMnxcu%(w)T-1zM z-1P%2U0XN1)tWE==D49WZ(vr7_mCyATc-CteEwjH{VT$Mx-UA^^g5;K&iFroZEnEF z1Kii%9HgG^pV_B)Y3>d>1YW_?NqWJ$v1;)$i#$wymDE+|6J@G19$3HPS z7}Lw)wAhJ_bHn{;zBT&T@s5(?h-VD-M-u=&j77*B?VT*=`^ZKfc&QS%A zv!`^KjAndyM3qSy!G?GXY3;<9Zc7V+Kv!|fk)sEFW7x+q#+f>1D9B;T|J}fsE*i1Z z<~VLWS(W&rp?D}225%ZHOBTc!j0s8f0uO3|DgI(pbv4k_4(-^c4qzJBjVoaUX^iyT z#V_CBbIjMHd;0j>oJ*vd8SjodmOIZLd+^JLjRV=JWrMXsLI@I$d-PK|j7K1Y$n08C z@^VMkbZyCdv?*+AooPB^0lb!}uw0HDoVp6h;^eZIDf*4SY?gi!e&+8As-%X+m7G3mvu3 zu5qK9z1E3f2+3|dr$PPWc0NlCW>WYJkI26ZiX4N1t>4^abUY2d@bi-9y2 literal 0 HcmV?d00001 diff --git a/_static/_img/offdrawmodel_05.gif b/_static/_img/offdrawmodel_05.gif new file mode 100644 index 0000000000000000000000000000000000000000..f9d6400ff903952f5e71b439afc716bdf995c3e3 GIT binary patch literal 1975 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 literal 0 HcmV?d00001 diff --git a/_static/_img/offdrawmodel_11.gif b/_static/_img/offdrawmodel_11.gif new file mode 100644 index 0000000000000000000000000000000000000000..0b8047fbd11f497472a7c93720c1c342bc26c6ac GIT binary patch literal 2020 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 literal 0 HcmV?d00001 diff --git a/_static/_img/offdrawmodel_30.gif b/_static/_img/offdrawmodel_30.gif new file mode 100644 index 0000000000000000000000000000000000000000..a6e9a6bb1e614a1b828f0d87deee12588f6ea94c GIT binary patch literal 2132 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 F{0|j8=57E0 literal 0 HcmV?d00001 diff --git a/_static/_img/ondrawmodel_07.gif b/_static/_img/ondrawmodel_07.gif new file mode 100644 index 0000000000000000000000000000000000000000..4ecd203149e860ab5a89dd53636512e1e4801a78 GIT binary patch literal 2973 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 literal 0 HcmV?d00001 diff --git a/_static/_img/ondrawmodel_13.gif b/_static/_img/ondrawmodel_13.gif new file mode 100644 index 0000000000000000000000000000000000000000..457dde39af38941b3bb6a1774b592775b1966433 GIT binary patch literal 1870 zcmdUwc~?_+0)~G#2_YLHtceh4K$fsc1jY^!rvd6H!eFdXD?$yzL13_rY*Mg#AruH} z*orI>LfHg_D_9dY=VHWSK@7@Fk>kw7fQrCKp!F1jlBpk~&nI}E^ZxN34E^h${bN!< zFnGxW`UDmLVEfh;z5E;u!}{!xha(vJvLk=7A?Wi$zVV~!+s^CzzSdvx&?h?^3a~ul~w@edTefRLWwp znwy(T0?fCYQw??TJKBFD2=b8$E`mkUXYAEC#!L!qc2*ZO8qK?|oT;g)cO$a-)6AW> z>mrdT+Lf}$0qR& zz}Nuua>aSy<`)!7ii%50%gUt{l~vU>-_>5Nt8ZwOU90nE>n7d&PX8 zh=|${Z1J+qvqjE8((xKXWh<#?#&zomdli@#*S<=+kDD6dZwO_9vU$CQUEr*eU3>q6%FJ6qI>Wt|37Ot#{@ z^r}cc*AO7--vV;07|n|!iDT#qCo>%E0$icF_9%t`?gT~&?oh|IUX`>neF*D>&)wi* z@!aGsR)`7hq=S>}vc9X;LMav#{U(|tj8e3mMA*g$!10ipASvx70b%2bJE_4^AmFJ2 z9^jW8$zYC-=9CM&rxD%wu1AW=H%NpL7q?`cuGIYeW%pW=Z4>2Y??T8;pa!abP5$4# z;fqO;@lJ07z?va*>b5VW^rIbK>uxq~$yphsAR5>Wfq*vh9mn_f7d1$mM~m=dQS5(>L1J@x?NYx)e% z>}MN+AgiupG|{BfzdqpJzt8^Qa$7jjJiAhR0u82oF50yTv1VMlI+)f3^ukudG8uT-FRT;H&^4vAlrisb2TZ=*LDo*_blpTfY zotw@OL7q`fUr`wC%xR67<9UC@hf_Hvivu4`*cT_Cm5wrn2`e1%LKFnejAEP={IPS) z=CM(jRiGUV4Z?HkIHy?9k)#|9MqF%P(#P119>81bc7Yxk>+*CG45d`Lj>Q_`LLbJN zV{+@~K9%?*kZn$jeL2OkY!JywajXS(>^Qem58_;o`It3K9Oy1BuKt2z=T^ul-@s|I1iIJtJ^!1 zkdG1YP0#SxZGX(Wx3~H=8Rxg#7_ZFtvyz(NW*^tvUWfJ!xJl@ol4kAB2!{x%2lHqW9Up{#y0CXs8TuoA;4 zDl2)cRoWUyj<(fk+r^elv7x;v(k0J6f5r3p3qJ4H`}KNn4Gdtr#uWlSco_-acL!t( z!T^}jW9yDEdKB_S*SC_R~4x;hw#!=Y)Y-;%OEDAP`TwGGGd`}Kheh2r^* ztwqN}7rFw}h=lij;YJ2}pFh6I;+xOU&udcA=Hg(LO7-z+xgcrRr*u^%3vT>0bP%A2Q;8o9j}1NnUZdTY}Q8Fmf%A#9fYr>T|?50YA2TR)B! zFc=ITkN0_bCUmREc$3FmySG3f*tBU=a$KZLCi^0ad%v3f;K2jO4OU)ToXi=9QQLg> zeGw{^N&~!I*3n6!?z#t~ObQQLUz0E$EHsjL*!NVpx;xVU<^7lX|31_ACaqa z|2Y9_t9Yb1M{+9nbYA|Mg2JNW5^3q#vUBIlD=NRKx=?+wrdC#0FK@VXx!y-xn~Qzh zavft`y=v0fAv4j&T-4RAV1*)#+($O*9vp(5H+X&by|UzrwwKFYIOv{%frf?~P(6P! zrJ8sWJmBntX^;G!W2nvA;M_fKux-oq$4@IN?~N>X=vQPYH(f5tz#i@MX41$kRLi9f z_ebcPQY1o|IkkwsGuob4H%YS&Mk{dvW@;TvBM5A|51DmR2-GyXmaOq%EhmRUIF3vF zk8TMPFui*%FKb}0ENvEgtZ=dx)hL76er@zR$E}(Ey5R!7( z*1!Q8MV}Lt-DwuT(&Nw=ji%mRjY?*%j*59DUd^ReeFbnpJlf{1X*4Up5>}u6 zD&+uS(ZVMvXJ1baF#7!X)wSDi<=;SV&Q}62st4Rpxjy(>XAY4&$cBi{M!QAzT~?`w z*dDr4oV;(_Q9HJU``Fxfqp#OA0x!Oq-?^PD?N&EOQ#u;K@SaDo+GLu{e7n5PPGp{4(xk(TU)CYd{gtwr!~nh=kI7gWvFKVA;xG?g zE&2zc8ckB2FmYAs!+0AG7vmaaICtaY3vjU@wcgu)p&Yv05yo;p0!JM|)k33Qpot7+*! z;uHP)#bqmp6YttRyxwMwbKCtvN#V4`%FpbjWFaWGzc`ic44z+PAg{VE7!$^aeD`Pp zS%GrBd4ek!ohqGF$7eq6cgj|k8dVxu{^KdQbMRS2s`VRFcBhr;Pay;L>&1Q{l?vBd z?zirL8lE01c2&f}vdo$&(S{$$P7!($HAt&vW}9wPf~T1kImz0)Y%KWb16BM@6pRhK zJd6|P)B<*lt>LYaDB8JQayY<3kB91~ZRC7st~oYK2JU7N6*KbP#QX0;g^Nez15ql? z4V~ttS0f?+*_zVMM6+g735Ql)OubJQ4%OLwN6$dV2j>eCHlT0T@jprGw1Cn!zIVh zH?1Qom$j0S0PHC{c;`i+CM-+!Vtu&sIFG`l3;xCk*khv6joU3-)#DXM?DE&A5RjPiqw0HNeYd@MkCZH18F0rM9 zM$B^l-I`ANVC{>b@%4>39msbSH=QO3bX#Nfeg0^%FfORsQOzk|TyKvigl)$i z>yLMT%Hl{2BljUzJVkje-+trw@5AT1i_&w1#z)8u;upunhJ?l6y$o$b>&5GkVgOUQ zh1w>V0-GI}_E+PF6%RkUN*UO~XY2R2RIgjX+hPA*wwLOjY4=+pbbTPoK6U3y%{BPT zvF!?Prw_vBp-m#Ag#mjybI!?WRk$895@iz%pXO5;f5zRt41ZY{&fm{VPD}1VGPgOW z??Dfec3p7IhbK?54ox43Ijnu^%n=&<+Y;TVNuD#Yr7O!!RG$%mRfmiS@kO z{R*v+-SGB_6WtckqC39EBH#fYd$R+ybNP^6W2a8|NW11fDUy3)0B8`vroZsmfr9R+=6W{M#$MVVF@Z?!Rbop;~BFF0)1 z`{c4pv8R`0?<+w~O~T9t7l3)l&aS&tyh4PV%j+E&blUY@c7ep+Qo% z%k6LzW0s6;DY*OjTUwz~tr~K~Av%9Q%on6+X=1I$bPRE1qU;%jAwcN>_6MkT2I{ZC zsj}URk!X28SXfFoV~clIWDat?qSH}Wif|a9oQRfR&ip}0GMPuZl~6+9dHFO15a|9f%Q09Fh7FAN59I20;JgvQe@a)!fphp4e;bcfdUB?z)87D z-AdTaCFeAzd5e+Z%!ecgAPP9^wt9uzIe5QdU!BfAp;(*;I>k|DFgWfM_DRL mqD_8GVtyMaXpb)F$SCNnEV$KKaC@xa&btD|7+C~>+kXLXMe-K_ literal 0 HcmV?d00001 diff --git a/_static/_img/ondrawmodel_20.gif b/_static/_img/ondrawmodel_20.gif new file mode 100644 index 0000000000000000000000000000000000000000..c0860fcda56c6f34535b5527e62765d9aeefe6a8 GIT binary patch literal 2073 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 literal 0 HcmV?d00001 diff --git a/_static/_img/ondrawmodel_26.gif b/_static/_img/ondrawmodel_26.gif new file mode 100644 index 0000000000000000000000000000000000000000..4166e4df41b0886f43f1f08193cee98d737ee3ae GIT binary patch literal 2185 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 VICZ8>&8k+n%GIuVl^sC<06SL;^lShC literal 0 HcmV?d00001 diff --git a/_static/_img/ondrawmodel_30.gif b/_static/_img/ondrawmodel_30.gif new file mode 100644 index 0000000000000000000000000000000000000000..e6bc161b63cd3333cec2758dfd1bf2337735c8c0 GIT binary patch literal 2088 zcmdUsjXRTj1Au?qo?+iJVXbs+sFu&6lsNT_k&x!l2T99Eq0)|$lDZzt=MgP7Ny;#i znHJSnIPW$jg;aFL573)q_tg26Nl8WO1h zfRU?NTFG_zSZ z3hd=+OU!2TaPx7kRtv*0l}df3Ynd9k+4EyWN&p^*MRnx|NVik&T}~DV1YZ}-{TDNo zM?C%f{3g{keU%AJCR0<)i}%CHWHPZ>d?PQ&j(}FFRPPN>u4b})mSX$P@e3kIBO@aQ zgTcub6X+`IQ5 z{xrX{8GYGH|F>tSv5e!ao^d+X5h#WS0gh%xq-s@-pa>t}%C^1U)WdM$u$cf0#h<|$+pV`rR%RYnv!an<^~4l&VMl;cY)6kcnBu;nK9 z>%TbNncJk~-DE!NqxR{sz~e%KScLqvgNHGI8_`7%DSIr952Wt53Zuw)7N?LI8`eWk z!PtC~98<1eoQEAR4OHJqIksq>>pr@k8=bS}_-h(h!`=nR^a$A(&CLus&H*o$8GRA5 zIx5Z}8R?%Hr|fR{b$6Z!(?=tBoN>|)tU#+P(L#3v=Fgel0M1cWXK@Kw@B2dY3BG(3 zHPKkUwjwYHu~!QOZYBNS7Us>7zdLkx>Xa{}36Pm-?*H}$_)phB7i=BL%k7^(L8V); zv&^_Wl4>kx!y88}0r1BSXO`+ibepF}g^`46SGqRlzgz(W;}o2W0M?rYttS*EO2n9E z-`1xPJ*eFB@y#GH&3;8V8+K z{^t|md}?Sm7wka`pVY?Q?nW|f+0<)|l4QZE);SKe4P`aZjbL5#@me&#UbY{FRkiJh z7>k(hz>AIOuK7^Gqcw%H7~Tx`!gk3M!cL{GuWIA~mVf&f;sc^q^% zo=$bsfOHiXWpq2K*8nziIp%GpP;d2|w&Ywf4anlbn&9k|b~K#k9pq!cAy}8$2=8vI zMY3p1+nj6W3b15#CW1BX6u-y0h!^Xw&-aF7z-O$`;9{*vITT9h>4pbQs!SiSF1Gih z4O0;ktT4$H(O2L5Kh`thgR zCiKhR&R9jtf$txrx%zD790^*}{q(@2q?LEcin*xz+pm;eZtnL&-AR*DwKbg)l)KGai za7dgb+fOXNtMwdY9_G(<;QunukJ)>MK0Ygr$o`}3!)7FLVCZ@UZVL)8w#Q$I1CAQ7 z<6+Yz&i@`Dunqaa)xTlBV!5gDu2D3!E(h`}TO!=#wATpB5sCb2Y1=w!_≀Ed!@i zg%E576ybc=v-r_0NzYy+xVy{gEHzs)z7;@dq-8d&^mkkZbj7G4)~C@dy9!QDL!t8$ zz&aiOODSh>`Db8=@PFrgRKG~XF`~{?mYP9$0%l9RlKXi(PgcnFPs#BNL!%#b)Hd7xl&H z*II`?bx2Y~MnrDDV3l;QwN1jk^;@GT(RSjoWd|19lReVF&ls2zcD!77RL?`T>DGtg z3Q~g~uWcUq-ZxkKaGyg+*)lqgwAB}(J+}?__qm@$qxR%54Mm#!Fl7&_YS)Ot&rb6; zDNeA(@r9g;sU_B|Ga$<+4X6TL5e38(9SnL5d literal 0 HcmV?d00001 diff --git a/_static/_img/ondrawmodel_34.gif b/_static/_img/ondrawmodel_34.gif new file mode 100644 index 0000000000000000000000000000000000000000..8c51fe97aaae1d8760050721276cd15555dcb82d GIT binary patch literal 2179 zcmdUujXzZR0>*#m%$YNTc{$!DN*Q6ALiJB&k$`T}!w2o|z`^G9i)5 z6lySPa)*>|9m-vbZEAHJk|vv*q`TU*&FICpf5v_Og75SBK2Koq2JcndGk_oXFAnqs z1^}2Pvkh|pxw$#L%xNtbG1P_{REZyN<$Zp3Tc5vBpSS4Chv|<$Rgxt6@oF|f5T72a z^{3b9tGuoY8K3Sq7;dCbWU~z&dkrUjXD@CwD5CUIj=t0d$8m#lv%c8gpib6T2oB-& znn>f>%e$9bQFJ<;p+3aJ!y_^>62q_r0V)&CbszkJB1LuuZ$zEq}4rIO3#TrT&^ zZ_jNpcu2&O$z&pts432*zrR16Pb~^E`pW#3|Nl331_S~C2hM+0_{#~P%@Mfdi1cV~ zUVcGgQE|z!QrYpc@`@9cC#$MY)to+awpM=bd=Y*6T-JiRI5=8b0qxN6laZ&x9+s9a-j|(w+t~d6qSZ>& z!E)Hno?=h6pcrN?sGq5$pmSUi>6Z(|Ien+t7N|%dtX#&nzZOW=qmY%yo)N`cI1l^c z_s2F&_M}*XMyNBc$c9W(-Gbt8w{v@r7SF>5&HFMDN$p~9;{pEI5*VZKEa;HnCw4|t z{7lDtzW~DA0}AWNkGg|gaJ-$hO~?NBX06xC6kH&F(QfTB7uzT|ZJK;ky$~1nYhsnp zZaw+5Z=lMq2V4aiy~OdI3lu z686y`H6ZElnEdVd!uSf<)7L*Bn9Uvscw|L5e=%-1;$QY-Q)D;S2sjg_Nl$HL1l1@_ zu=wx|JAxVQvgYBpjK|YFKb+%D0#6!Wv|}!Z2kUMhEK}x(N1B5QfDGAGlThf^!1xmm ziicJXd__h$-4!0hD-myba`5~?z8wX#vF1ou=US6hrT!S64J@#2I8#(mf|#XZmGFF0 zt{`ZbP8=th)W0};T+q8d85ZHG6eI1clQ0h>9P1H%%u+z3l4tE1A<~5WQ3srCF|#Tx zp>bwbF9q%)8WP3s6!0kv(u@eByD2;1^E}}WG0f5Aj339o{v1A6DLr+p<>qjZQro|^ zjKUlV!P`K#z!|Vc0Er@^#+EZIWldTQrrE2Y2mlG72e2Hp&F^>(RE9+&LNQv^d3Rr_ z79-}Aux7pnn%HjwkiBpyftn%Czc;oodIdoT4l;1cMJF!g`8Fj};5jpUlmPbq@5z6-QW3c5C@E;#p&E+n)HUV{2C6@inIhy1n*pde_R- zR=4%WkL|O6I-;p68I=~jcLYw?oC-ABi2$`Ht@N~GrP&RmsroCnHOxV+Zou*7b)N-# zomO2?(jH40Tvy&aGeMsO*bnEtIH~ewU}|i6%XyZsQ%>)f!YTFBH$OATIVM3N-8~yP zw&@pv23=8o{|%2gHY$)46qc<}e2y`q`UWBP;!|Ij6dctI84Ce}E>JEIh_-W|;AOt} z5|pEg_9Dv$xxjaSM-Xt>{fNce?na}A0BgdWW^#d(pJ#d6fg3)|!_)j?qA7OyEDVBw${r^pr*G(ta@OajMeHh!&stlv?FpDAKuQa7RG&9Be$XX6^D|mDB|_$-;uKnvFrR1t`1KZxKUU zhd6N8nHaw|=5*lIl{@cvB&Nf{UODpp8`L`+8|LW8>UsoItjL7}fM cY3S{qljuak{+ySg&t``|+|;)m-~!&1u}A`t?OF7Z|1gRivOgXi&7IyQd1Pl zGfOfQ60;I3a`F>X^fL3(@);C=vM_KlFfb_o=k{|A33hf2a5d61U}gjg=>Rd%XaNQW zW@Cw{|b%Y*pl8F?4B9 zlo4Fz*0kZGJabY|>}Okf0}CCg{u4`zEPY^pV?j2@h+|igy0+Kz6p;@SpM4s6)XEMg z#3Y4GX>Hjlml5ftdH$4x0JGdn8~MX(U~_^d!Hi)=HU{V%g+mi8#UGbE-*ao8f#h+S z2a0-5+vc7MU$e-NhmBjLIC1v|)9+Im8x1yacJ7{^tLX(ZhYi^rpmXm0`@ku9b53aN zEXH@Y3JaztblgpxbJt{AtE1ad1Ca>{v$rwwvK(>{m~Gf_=-Ro7Fk{#;i~+{{>QtvI yb2P8Zac~?~=sRA>$6{!(^3;ZP0TPFR(G_-UDU(8Jl0?(IXu$~#4A!880|o%~Al1tN literal 0 HcmV?d00001 diff --git a/_static/basic.css b/_static/basic.css new file mode 100644 index 0000000..7ed0e58 --- /dev/null +++ b/_static/basic.css @@ -0,0 +1,632 @@ +/* + * basic.css + * ~~~~~~~~~ + * + * Sphinx stylesheet -- basic theme. + * + * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox input[type="text"] { + width: 170px; +} + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin: 10px 0 0 20px; + padding: 0; +} + +ul.search li { + padding: 5px 0 5px 20px; + background-image: url(file.png); + background-repeat: no-repeat; + background-position: 0 7px; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li div.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px 7px 0 7px; + background-color: #ffe; + width: 40%; + float: right; +} + +p.sidebar-title { + font-weight: bold; +} + +/* -- topics ---------------------------------------------------------------- */ + +div.topic { + border: 1px solid #ccc; + padding: 7px 7px 0 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +div.admonition dl { + margin-bottom: 0; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + border: 0; + border-collapse: collapse; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +table.footnote td, table.footnote th { + border: 0 !important; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +dl { + margin-bottom: 15px; +} + +dd p { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +dt:target, .highlighted { + background-color: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; +} + +td.linenos pre { + padding: 5px 0px; + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + margin-left: 0.5em; +} + +table.highlighttable td { + padding: 0 0.5em 0 0.5em; +} + +div.code-block-caption { + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +div.code-block-caption + div > div.highlight > pre { + margin-top: 0; +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + padding: 1em 1em 0; +} + +div.literal-block-wrapper div.highlight { + margin: 0; +} + +code.descname { + background-color: transparent; + font-weight: bold; + font-size: 1.2em; +} + +code.descclassname { + background-color: transparent; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: relative; + left: 0px; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/_static/comment-bright.png b/_static/comment-bright.png new file mode 100644 index 0000000000000000000000000000000000000000..15e27edb12ac25701ac0ac21b97b52bb4e45415e GIT binary patch literal 756 zcmVgfIX78 z$8Pzv({A~p%??+>KickCb#0FM1rYN=mBmQ&Nwp<#JXUhU;{|)}%&s>suq6lXw*~s{ zvHx}3C%<;wE5CH!BR{p5@ml9ws}y)=QN-kL2?#`S5d*6j zk`h<}j1>tD$b?4D^N9w}-k)bxXxFg>+#kme^xx#qg6FI-%iv2U{0h(Y)cs%5a|m%Pn_K3X_bDJ>EH#(Fb73Z zfUt2Q3B>N+ot3qb*DqbTZpFIn4a!#_R-}{?-~Hs=xSS6p&$sZ-k1zDdtqU`Y@`#qL z&zv-~)Q#JCU(dI)Hf;$CEnK=6CK50}q7~wdbI->?E07bJ0R;!GSQTs5Am`#;*WHjvHRvY?&$Lm-vq1a_BzocI^ULXV!lbMd%|^B#fY;XX)n<&R^L z=84u1e_3ziq;Hz-*k5~zwY3*oDKt0;bM@M@@89;@m*4RFgvvM_4;5LB!@OB@^WbVT zjl{t;a8_>od-~P4 m{5|DvB&z#xT;*OnJqG}gk~_7HcNkCr0000W zanA~u9RIXo;n7c96&U)YLgs-FGlx~*_c{Jgvesu1E5(8YEf&5wF=YFPcRe@1=MJmi zag(L*xc2r0(slpcN!vC5CUju;vHJkHc*&70_n2OZsK%O~A=!+YIw z7zLLl7~Z+~RgWOQ=MI6$#0pvpu$Q43 zP@36QAmu6!_9NPM?o<1_!+stoVRRZbW9#SPe!n;#A_6m8f}|xN1;H{`0RoXQ2LM47 zt(g;iZ6|pCb@h2xk&(}S3=EVBUO0e90m2Lp5CB<(SPIaB;n4))3JB87Or#XPOPcum z?<^(g+m9}VNn4Y&B`g8h{t_$+RB1%HKRY6fjtd-<7&EsU;vs0GM(Lmbhi%Gwcfs0FTF}T zL{_M6Go&E0Eg8FuB*(Yn+Z*RVTBE@10eIOb3El^MhO`GabDll(V0&FlJi2k^;q8af zkENdk2}x2)_KVp`5OAwXZM;dG0?M-S)xE1IKDi6BY@5%Or?#aZ9$gcX)dPZ&wA1a< z$rFXHPn|TBf`e?>Are8sKtKrKcjF$i^lp!zkL?C|y^vlHr1HXeVJd;1I~g&Ob-q)& z(fn7s-KI}G{wnKzg_U5G(V%bX6uk zIa+<@>rdmZYd!9Y=C0cuchrbIjuRB_Wq{-RXlic?flu1*_ux}x%(HDH&nT`k^xCeC ziHi1!ChH*sQ6|UqJpTTzX$aw8e(UfcS^f;6yBWd+(1-70zU(rtxtqR%j z-lsH|CKQJXqD{+F7V0OTv8@{~(wp(`oIP^ZykMWgR>&|RsklFMCnOo&Bd{le} zV5F6424Qzl;o2G%oVvmHgRDP9!=rK8fy^!yV8y*4p=??uIRrrr0?>O!(z*g5AvL2!4z0{sq%vhG*Po}`a<6%kTK5TNhtC8}rXNu&h^QH4A&Sk~Autm*s~45(H7+0bi^MraaRVzr05hQ3iK?j` zR#U@^i0WhkIHTg29u~|ypU?sXCQEQgXfObPW;+0YAF;|5XyaMAEM0sQ@4-xCZe=0e z7r$ofiAxn@O5#RodD8rh5D@nKQ;?lcf@tg4o+Wp44aMl~c47azN_(im0N)7OqdPBC zGw;353_o$DqGRDhuhU$Eaj!@m000000NkvXXu0mjfjZ7Z_ literal 0 HcmV?d00001 diff --git a/_static/doctools.js b/_static/doctools.js new file mode 100644 index 0000000..8163495 --- /dev/null +++ b/_static/doctools.js @@ -0,0 +1,287 @@ +/* + * doctools.js + * ~~~~~~~~~~~ + * + * Sphinx JavaScript utilities for all documentation. + * + * :copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +/** + * select a different prefix for underscore + */ +$u = _.noConflict(); + +/** + * make the code below compatible with browsers without + * an installed firebug like debugger +if (!window.console || !console.firebug) { + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", + "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", + "profile", "profileEnd"]; + window.console = {}; + for (var i = 0; i < names.length; ++i) + window.console[names[i]] = function() {}; +} + */ + +/** + * small helper function to urldecode strings + */ +jQuery.urldecode = function(x) { + return decodeURIComponent(x).replace(/\+/g, ' '); +}; + +/** + * small helper function to urlencode strings + */ +jQuery.urlencode = encodeURIComponent; + +/** + * This function returns the parsed url parameters of the + * current request. Multiple values per key are supported, + * it will always return arrays of strings for the value parts. + */ +jQuery.getQueryParameters = function(s) { + if (typeof s == 'undefined') + s = document.location.search; + var parts = s.substr(s.indexOf('?') + 1).split('&'); + var result = {}; + for (var i = 0; i < parts.length; i++) { + var tmp = parts[i].split('=', 2); + var key = jQuery.urldecode(tmp[0]); + var value = jQuery.urldecode(tmp[1]); + if (key in result) + result[key].push(value); + else + result[key] = [value]; + } + return result; +}; + +/** + * highlight a given string on a jquery object by wrapping it in + * span elements with the given class name. + */ +jQuery.fn.highlightText = function(text, className) { + function highlight(node) { + if (node.nodeType == 3) { + var val = node.nodeValue; + var pos = val.toLowerCase().indexOf(text); + if (pos >= 0 && !jQuery(node.parentNode).hasClass(className)) { + var span = document.createElement("span"); + span.className = className; + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + node.parentNode.insertBefore(span, node.parentNode.insertBefore( + document.createTextNode(val.substr(pos + text.length)), + node.nextSibling)); + node.nodeValue = val.substr(0, pos); + } + } + else if (!jQuery(node).is("button, select, textarea")) { + jQuery.each(node.childNodes, function() { + highlight(this); + }); + } + } + return this.each(function() { + highlight(this); + }); +}; + +/* + * backward compatibility for jQuery.browser + * This will be supported until firefox bug is fixed. + */ +if (!jQuery.browser) { + jQuery.uaMatch = function(ua) { + ua = ua.toLowerCase(); + + var match = /(chrome)[ \/]([\w.]+)/.exec(ua) || + /(webkit)[ \/]([\w.]+)/.exec(ua) || + /(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) || + /(msie) ([\w.]+)/.exec(ua) || + ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) || + []; + + return { + browser: match[ 1 ] || "", + version: match[ 2 ] || "0" + }; + }; + jQuery.browser = {}; + jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true; +} + +/** + * Small JavaScript module for the documentation. + */ +var Documentation = { + + init : function() { + this.fixFirefoxAnchorBug(); + this.highlightSearchWords(); + this.initIndexTable(); + + }, + + /** + * i18n support + */ + TRANSLATIONS : {}, + PLURAL_EXPR : function(n) { return n == 1 ? 0 : 1; }, + LOCALE : 'unknown', + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext : function(string) { + var translated = Documentation.TRANSLATIONS[string]; + if (typeof translated == 'undefined') + return string; + return (typeof translated == 'string') ? translated : translated[0]; + }, + + ngettext : function(singular, plural, n) { + var translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated == 'undefined') + return (n == 1) ? singular : plural; + return translated[Documentation.PLURALEXPR(n)]; + }, + + addTranslations : function(catalog) { + for (var key in catalog.messages) + this.TRANSLATIONS[key] = catalog.messages[key]; + this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')'); + this.LOCALE = catalog.locale; + }, + + /** + * add context elements like header anchor links + */ + addContextElements : function() { + $('div[id] > :header:first').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this headline')). + appendTo(this); + }); + $('dt[id]').each(function() { + $('\u00B6'). + attr('href', '#' + this.id). + attr('title', _('Permalink to this definition')). + appendTo(this); + }); + }, + + /** + * workaround a firefox stupidity + * see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075 + */ + fixFirefoxAnchorBug : function() { + if (document.location.hash) + window.setTimeout(function() { + document.location.href += ''; + }, 10); + }, + + /** + * highlight the search words provided in the url in the text + */ + highlightSearchWords : function() { + var params = $.getQueryParameters(); + var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : []; + if (terms.length) { + var body = $('div.body'); + if (!body.length) { + body = $('body'); + } + window.setTimeout(function() { + $.each(terms, function() { + body.highlightText(this.toLowerCase(), 'highlighted'); + }); + }, 10); + $('

') + .appendTo($('#searchbox')); + } + }, + + /** + * init the domain index toggle buttons + */ + initIndexTable : function() { + var togglers = $('img.toggler').click(function() { + var src = $(this).attr('src'); + var idnum = $(this).attr('id').substr(7); + $('tr.cg-' + idnum).toggle(); + if (src.substr(-9) == 'minus.png') + $(this).attr('src', src.substr(0, src.length-9) + 'plus.png'); + else + $(this).attr('src', src.substr(0, src.length-8) + 'minus.png'); + }).css('display', ''); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) { + togglers.click(); + } + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords : function() { + $('#searchbox .highlight-link').fadeOut(300); + $('span.highlighted').removeClass('highlighted'); + }, + + /** + * make the url absolute + */ + makeURL : function(relativeURL) { + return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL; + }, + + /** + * get the current relative url + */ + getCurrentURL : function() { + var path = document.location.pathname; + var parts = path.split(/\//); + $.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() { + if (this == '..') + parts.pop(); + }); + var url = parts.join('/'); + return path.substring(url.lastIndexOf('/') + 1, path.length - 1); + }, + + initOnKeyListeners: function() { + $(document).keyup(function(event) { + var activeElementType = document.activeElement.tagName; + // don't navigate when in search box or textarea + if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT') { + switch (event.keyCode) { + case 37: // left + var prevHref = $('link[rel="prev"]').prop('href'); + if (prevHref) { + window.location.href = prevHref; + return false; + } + case 39: // right + var nextHref = $('link[rel="next"]').prop('href'); + if (nextHref) { + window.location.href = nextHref; + return false; + } + } + } + }); + } +}; + +// quick alias for translations +_ = Documentation.gettext; + +$(document).ready(function() { + Documentation.init(); +}); \ No newline at end of file diff --git a/_static/down-pressed.png b/_static/down-pressed.png new file mode 100644 index 0000000000000000000000000000000000000000..5756c8cad8854722893dc70b9eb4bb0400343a39 GIT binary patch literal 222 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`OFdm2Ln;`PZ^+1>KjR?B@S0W7 z%OS_REiHONoJ6{+Ks@6k3590|7k9F+ddB6!zw3#&!aw#S`x}3V3&=A(a#84O-&F7T z^k3tZB;&iR9siw0|F|E|DAL<8r-F4!1H-;1{e*~yAKZN5f0|Ei6yUmR#Is)EM(Po_ zi`qJR6|P<~+)N+kSDgL7AjdIC_!O7Q?eGb+L+qOjm{~LLinM4NHn7U%HcK%uoMYO5 VJ~8zD2B3o(JYD@<);T3K0RV0%P>BEl literal 0 HcmV?d00001 diff --git a/_static/down.png b/_static/down.png new file mode 100644 index 0000000000000000000000000000000000000000..1b3bdad2ceffae91cee61b32f3295f9bbe646e48 GIT binary patch literal 202 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6CVIL!hEy=F?b*7pIY7kW{q%Rg zx!yQ<9v8bmJwa`TQk7YSw}WVQ()mRdQ;TC;* literal 0 HcmV?d00001 diff --git a/_static/file.png b/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 GIT binary patch literal 286 zcmV+(0pb3MP)s`hMrGg#P~ix$^RISR_I47Y|r1 z_CyJOe}D1){SET-^Amu_i71Lt6eYfZjRyw@I6OQAIXXHDfiX^GbOlHe=Ae4>0m)d(f|Me07*qoM6N<$f}vM^LjV8( literal 0 HcmV?d00001 diff --git a/_static/jquery-3.1.0.js b/_static/jquery-3.1.0.js new file mode 100644 index 0000000..f2fc274 --- /dev/null +++ b/_static/jquery-3.1.0.js @@ -0,0 +1,10074 @@ +/*eslint-disable no-unused-vars*/ +/*! + * jQuery JavaScript Library v3.1.0 + * https://jquery.com/ + * + * Includes Sizzle.js + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * https://jquery.org/license + * + * Date: 2016-07-07T21:44Z + */ +( function( global, factory ) { + + "use strict"; + + if ( typeof module === "object" && typeof module.exports === "object" ) { + + // For CommonJS and CommonJS-like environments where a proper `window` + // is present, execute the factory and get jQuery. + // For environments that do not have a `window` with a `document` + // (such as Node.js), expose a factory as module.exports. + // This accentuates the need for the creation of a real `window`. + // e.g. var jQuery = require("jquery")(window); + // See ticket #14549 for more info. + module.exports = global.document ? + factory( global, true ) : + function( w ) { + if ( !w.document ) { + throw new Error( "jQuery requires a window with a document" ); + } + return factory( w ); + }; + } else { + factory( global ); + } + +// Pass this if window is not defined yet +} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { + +// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 +// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode +// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common +// enough that all such attempts are guarded in a try block. +"use strict"; + +var arr = []; + +var document = window.document; + +var getProto = Object.getPrototypeOf; + +var slice = arr.slice; + +var concat = arr.concat; + +var push = arr.push; + +var indexOf = arr.indexOf; + +var class2type = {}; + +var toString = class2type.toString; + +var hasOwn = class2type.hasOwnProperty; + +var fnToString = hasOwn.toString; + +var ObjectFunctionString = fnToString.call( Object ); + +var support = {}; + + + + function DOMEval( code, doc ) { + doc = doc || document; + + var script = doc.createElement( "script" ); + + script.text = code; + doc.head.appendChild( script ).parentNode.removeChild( script ); + } +/* global Symbol */ +// Defining this global in .eslintrc would create a danger of using the global +// unguarded in another place, it seems safer to define global only for this module + + + +var + version = "3.1.0", + + // Define a local copy of jQuery + jQuery = function( selector, context ) { + + // The jQuery object is actually just the init constructor 'enhanced' + // Need init if jQuery is called (just allow error to be thrown if not included) + return new jQuery.fn.init( selector, context ); + }, + + // Support: Android <=4.0 only + // Make sure we trim BOM and NBSP + rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, + + // Matches dashed string for camelizing + rmsPrefix = /^-ms-/, + rdashAlpha = /-([a-z])/g, + + // Used by jQuery.camelCase as callback to replace() + fcamelCase = function( all, letter ) { + return letter.toUpperCase(); + }; + +jQuery.fn = jQuery.prototype = { + + // The current version of jQuery being used + jquery: version, + + constructor: jQuery, + + // The default length of a jQuery object is 0 + length: 0, + + toArray: function() { + return slice.call( this ); + }, + + // Get the Nth element in the matched element set OR + // Get the whole matched element set as a clean array + get: function( num ) { + return num != null ? + + // Return just the one element from the set + ( num < 0 ? this[ num + this.length ] : this[ num ] ) : + + // Return all the elements in a clean array + slice.call( this ); + }, + + // Take an array of elements and push it onto the stack + // (returning the new matched element set) + pushStack: function( elems ) { + + // Build a new jQuery matched element set + var ret = jQuery.merge( this.constructor(), elems ); + + // Add the old object onto the stack (as a reference) + ret.prevObject = this; + + // Return the newly-formed element set + return ret; + }, + + // Execute a callback for every element in the matched set. + each: function( callback ) { + return jQuery.each( this, callback ); + }, + + map: function( callback ) { + return this.pushStack( jQuery.map( this, function( elem, i ) { + return callback.call( elem, i, elem ); + } ) ); + }, + + slice: function() { + return this.pushStack( slice.apply( this, arguments ) ); + }, + + first: function() { + return this.eq( 0 ); + }, + + last: function() { + return this.eq( -1 ); + }, + + eq: function( i ) { + var len = this.length, + j = +i + ( i < 0 ? len : 0 ); + return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] ); + }, + + end: function() { + return this.prevObject || this.constructor(); + }, + + // For internal use only. + // Behaves like an Array's method, not like a jQuery method. + push: push, + sort: arr.sort, + splice: arr.splice +}; + +jQuery.extend = jQuery.fn.extend = function() { + var options, name, src, copy, copyIsArray, clone, + target = arguments[ 0 ] || {}, + i = 1, + length = arguments.length, + deep = false; + + // Handle a deep copy situation + if ( typeof target === "boolean" ) { + deep = target; + + // Skip the boolean and the target + target = arguments[ i ] || {}; + i++; + } + + // Handle case when target is a string or something (possible in deep copy) + if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { + target = {}; + } + + // Extend jQuery itself if only one argument is passed + if ( i === length ) { + target = this; + i--; + } + + for ( ; i < length; i++ ) { + + // Only deal with non-null/undefined values + if ( ( options = arguments[ i ] ) != null ) { + + // Extend the base object + for ( name in options ) { + src = target[ name ]; + copy = options[ name ]; + + // Prevent never-ending loop + if ( target === copy ) { + continue; + } + + // Recurse if we're merging plain objects or arrays + if ( deep && copy && ( jQuery.isPlainObject( copy ) || + ( copyIsArray = jQuery.isArray( copy ) ) ) ) { + + if ( copyIsArray ) { + copyIsArray = false; + clone = src && jQuery.isArray( src ) ? src : []; + + } else { + clone = src && jQuery.isPlainObject( src ) ? src : {}; + } + + // Never move original objects, clone them + target[ name ] = jQuery.extend( deep, clone, copy ); + + // Don't bring in undefined values + } else if ( copy !== undefined ) { + target[ name ] = copy; + } + } + } + } + + // Return the modified object + return target; +}; + +jQuery.extend( { + + // Unique for each copy of jQuery on the page + expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ), + + // Assume jQuery is ready without the ready module + isReady: true, + + error: function( msg ) { + throw new Error( msg ); + }, + + noop: function() {}, + + isFunction: function( obj ) { + return jQuery.type( obj ) === "function"; + }, + + isArray: Array.isArray, + + isWindow: function( obj ) { + return obj != null && obj === obj.window; + }, + + isNumeric: function( obj ) { + + // As of jQuery 3.0, isNumeric is limited to + // strings and numbers (primitives or objects) + // that can be coerced to finite numbers (gh-2662) + var type = jQuery.type( obj ); + return ( type === "number" || type === "string" ) && + + // parseFloat NaNs numeric-cast false positives ("") + // ...but misinterprets leading-number strings, particularly hex literals ("0x...") + // subtraction forces infinities to NaN + !isNaN( obj - parseFloat( obj ) ); + }, + + isPlainObject: function( obj ) { + var proto, Ctor; + + // Detect obvious negatives + // Use toString instead of jQuery.type to catch host objects + if ( !obj || toString.call( obj ) !== "[object Object]" ) { + return false; + } + + proto = getProto( obj ); + + // Objects with no prototype (e.g., `Object.create( null )`) are plain + if ( !proto ) { + return true; + } + + // Objects with prototype are plain iff they were constructed by a global Object function + Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor; + return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString; + }, + + isEmptyObject: function( obj ) { + + /* eslint-disable no-unused-vars */ + // See https://github.com/eslint/eslint/issues/6125 + var name; + + for ( name in obj ) { + return false; + } + return true; + }, + + type: function( obj ) { + if ( obj == null ) { + return obj + ""; + } + + // Support: Android <=2.3 only (functionish RegExp) + return typeof obj === "object" || typeof obj === "function" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; + }, + + // Evaluates a script in a global context + globalEval: function( code ) { + DOMEval( code ); + }, + + // Convert dashed to camelCase; used by the css and data modules + // Support: IE <=9 - 11, Edge 12 - 13 + // Microsoft forgot to hump their vendor prefix (#9572) + camelCase: function( string ) { + return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); + }, + + nodeName: function( elem, name ) { + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + }, + + each: function( obj, callback ) { + var length, i = 0; + + if ( isArrayLike( obj ) ) { + length = obj.length; + for ( ; i < length; i++ ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } else { + for ( i in obj ) { + if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) { + break; + } + } + } + + return obj; + }, + + // Support: Android <=4.0 only + trim: function( text ) { + return text == null ? + "" : + ( text + "" ).replace( rtrim, "" ); + }, + + // results is for internal usage only + makeArray: function( arr, results ) { + var ret = results || []; + + if ( arr != null ) { + if ( isArrayLike( Object( arr ) ) ) { + jQuery.merge( ret, + typeof arr === "string" ? + [ arr ] : arr + ); + } else { + push.call( ret, arr ); + } + } + + return ret; + }, + + inArray: function( elem, arr, i ) { + return arr == null ? -1 : indexOf.call( arr, elem, i ); + }, + + // Support: Android <=4.0 only, PhantomJS 1 only + // push.apply(_, arraylike) throws on ancient WebKit + merge: function( first, second ) { + var len = +second.length, + j = 0, + i = first.length; + + for ( ; j < len; j++ ) { + first[ i++ ] = second[ j ]; + } + + first.length = i; + + return first; + }, + + grep: function( elems, callback, invert ) { + var callbackInverse, + matches = [], + i = 0, + length = elems.length, + callbackExpect = !invert; + + // Go through the array, only saving the items + // that pass the validator function + for ( ; i < length; i++ ) { + callbackInverse = !callback( elems[ i ], i ); + if ( callbackInverse !== callbackExpect ) { + matches.push( elems[ i ] ); + } + } + + return matches; + }, + + // arg is for internal usage only + map: function( elems, callback, arg ) { + var length, value, + i = 0, + ret = []; + + // Go through the array, translating each of the items to their new values + if ( isArrayLike( elems ) ) { + length = elems.length; + for ( ; i < length; i++ ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + + // Go through every key on the object, + } else { + for ( i in elems ) { + value = callback( elems[ i ], i, arg ); + + if ( value != null ) { + ret.push( value ); + } + } + } + + // Flatten any nested arrays + return concat.apply( [], ret ); + }, + + // A global GUID counter for objects + guid: 1, + + // Bind a function to a context, optionally partially applying any + // arguments. + proxy: function( fn, context ) { + var tmp, args, proxy; + + if ( typeof context === "string" ) { + tmp = fn[ context ]; + context = fn; + fn = tmp; + } + + // Quick check to determine if target is callable, in the spec + // this throws a TypeError, but we will just return undefined. + if ( !jQuery.isFunction( fn ) ) { + return undefined; + } + + // Simulated bind + args = slice.call( arguments, 2 ); + proxy = function() { + return fn.apply( context || this, args.concat( slice.call( arguments ) ) ); + }; + + // Set the guid of unique handler to the same of original handler, so it can be removed + proxy.guid = fn.guid = fn.guid || jQuery.guid++; + + return proxy; + }, + + now: Date.now, + + // jQuery.support is not used in Core but other projects attach their + // properties to it so it needs to exist. + support: support +} ); + +if ( typeof Symbol === "function" ) { + jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ]; +} + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), +function( i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); +} ); + +function isArrayLike( obj ) { + + // Support: real iOS 8.2 only (not reproducible in simulator) + // `in` check used to prevent JIT error (gh-2145) + // hasOwn isn't used here due to false negatives + // regarding Nodelist length in IE + var length = !!obj && "length" in obj && obj.length, + type = jQuery.type( obj ); + + if ( type === "function" || jQuery.isWindow( obj ) ) { + return false; + } + + return type === "array" || length === 0 || + typeof length === "number" && length > 0 && ( length - 1 ) in obj; +} +var Sizzle = +/*! + * Sizzle CSS Selector Engine v2.3.0 + * https://sizzlejs.com/ + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license + * http://jquery.org/license + * + * Date: 2016-01-04 + */ +(function( window ) { + +var i, + support, + Expr, + getText, + isXML, + tokenize, + compile, + select, + outermostContext, + sortInput, + hasDuplicate, + + // Local document vars + setDocument, + document, + docElem, + documentIsHTML, + rbuggyQSA, + rbuggyMatches, + matches, + contains, + + // Instance-specific data + expando = "sizzle" + 1 * new Date(), + preferredDoc = window.document, + dirruns = 0, + done = 0, + classCache = createCache(), + tokenCache = createCache(), + compilerCache = createCache(), + sortOrder = function( a, b ) { + if ( a === b ) { + hasDuplicate = true; + } + return 0; + }, + + // Instance methods + hasOwn = ({}).hasOwnProperty, + arr = [], + pop = arr.pop, + push_native = arr.push, + push = arr.push, + slice = arr.slice, + // Use a stripped-down indexOf as it's faster than native + // https://jsperf.com/thor-indexof-vs-for/5 + indexOf = function( list, elem ) { + var i = 0, + len = list.length; + for ( ; i < len; i++ ) { + if ( list[i] === elem ) { + return i; + } + } + return -1; + }, + + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped", + + // Regular expressions + + // http://www.w3.org/TR/css3-selectors/#whitespace + whitespace = "[\\x20\\t\\r\\n\\f]", + + // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier + identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+", + + // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + + // Operator (capture 2) + "*([*^$|!~]?=)" + whitespace + + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" + "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + + "*\\]", + + pseudos = ":(" + identifier + ")(?:\\((" + + // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments: + // 1. quoted (capture 3; capture 4 or capture 5) + "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" + + // 2. simple (capture 6) + "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" + + // 3. anything else (capture 2) + ".*" + + ")\\)|)", + + // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter + rwhitespace = new RegExp( whitespace + "+", "g" ), + rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), + + rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), + rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ), + + rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ), + + rpseudo = new RegExp( pseudos ), + ridentifier = new RegExp( "^" + identifier + "$" ), + + matchExpr = { + "ID": new RegExp( "^#(" + identifier + ")" ), + "CLASS": new RegExp( "^\\.(" + identifier + ")" ), + "TAG": new RegExp( "^(" + identifier + "|[*])" ), + "ATTR": new RegExp( "^" + attributes ), + "PSEUDO": new RegExp( "^" + pseudos ), + "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace + + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + // For use in libraries implementing .is() + // We use this for POS matching in `select` + "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) + }, + + rinputs = /^(?:input|select|textarea|button)$/i, + rheader = /^h\d$/i, + + rnative = /^[^{]+\{\s*\[native \w/, + + // Easily-parseable/retrievable ID or TAG or CLASS selectors + rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, + + rsibling = /[+~]/, + + // CSS escapes + // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ), + funescape = function( _, escaped, escapedWhitespace ) { + var high = "0x" + escaped - 0x10000; + // NaN means non-codepoint + // Support: Firefox<24 + // Workaround erroneous numeric interpretation of +"0x" + return high !== high || escapedWhitespace ? + escaped : + high < 0 ? + // BMP codepoint + String.fromCharCode( high + 0x10000 ) : + // Supplemental Plane codepoint (surrogate pair) + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); + }, + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g, + fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }, + + // Used for iframes + // See setDocument() + // Removing the function wrapper causes a "Permission Denied" + // error in IE + unloadHandler = function() { + setDocument(); + }, + + disabledAncestor = addCombinator( + function( elem ) { + return elem.disabled === true; + }, + { dir: "parentNode", next: "legend" } + ); + +// Optimize for push.apply( _, NodeList ) +try { + push.apply( + (arr = slice.call( preferredDoc.childNodes )), + preferredDoc.childNodes + ); + // Support: Android<4.0 + // Detect silently failing push.apply + arr[ preferredDoc.childNodes.length ].nodeType; +} catch ( e ) { + push = { apply: arr.length ? + + // Leverage slice if possible + function( target, els ) { + push_native.apply( target, slice.call(els) ); + } : + + // Support: IE<9 + // Otherwise append directly + function( target, els ) { + var j = target.length, + i = 0; + // Can't trust NodeList.length + while ( (target[j++] = els[i++]) ) {} + target.length = j - 1; + } + }; +} + +function Sizzle( selector, context, results, seed ) { + var m, i, elem, nid, match, groups, newSelector, + newContext = context && context.ownerDocument, + + // nodeType defaults to 9, since context defaults to document + nodeType = context ? context.nodeType : 9; + + results = results || []; + + // Return early from calls with invalid selector or context + if ( typeof selector !== "string" || !selector || + nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) { + + return results; + } + + // Try to shortcut find operations (as opposed to filters) in HTML documents + if ( !seed ) { + + if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) { + setDocument( context ); + } + context = context || document; + + if ( documentIsHTML ) { + + // If the selector is sufficiently simple, try using a "get*By*" DOM method + // (excepting DocumentFragment context, where the methods don't exist) + if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) { + + // ID selector + if ( (m = match[1]) ) { + + // Document context + if ( nodeType === 9 ) { + if ( (elem = context.getElementById( m )) ) { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( elem.id === m ) { + results.push( elem ); + return results; + } + } else { + return results; + } + + // Element context + } else { + + // Support: IE, Opera, Webkit + // TODO: identify versions + // getElementById can match elements by name instead of ID + if ( newContext && (elem = newContext.getElementById( m )) && + contains( context, elem ) && + elem.id === m ) { + + results.push( elem ); + return results; + } + } + + // Type selector + } else if ( match[2] ) { + push.apply( results, context.getElementsByTagName( selector ) ); + return results; + + // Class selector + } else if ( (m = match[3]) && support.getElementsByClassName && + context.getElementsByClassName ) { + + push.apply( results, context.getElementsByClassName( m ) ); + return results; + } + } + + // Take advantage of querySelectorAll + if ( support.qsa && + !compilerCache[ selector + " " ] && + (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { + + if ( nodeType !== 1 ) { + newContext = context; + newSelector = selector; + + // qSA looks outside Element context, which is not what we want + // Thanks to Andrew Dupont for this workaround technique + // Support: IE <=8 + // Exclude object elements + } else if ( context.nodeName.toLowerCase() !== "object" ) { + + // Capture the context ID, setting it first if necessary + if ( (nid = context.getAttribute( "id" )) ) { + nid = nid.replace( rcssescape, fcssescape ); + } else { + context.setAttribute( "id", (nid = expando) ); + } + + // Prefix every selector in the list + groups = tokenize( selector ); + i = groups.length; + while ( i-- ) { + groups[i] = "#" + nid + " " + toSelector( groups[i] ); + } + newSelector = groups.join( "," ); + + // Expand context for sibling selectors + newContext = rsibling.test( selector ) && testContext( context.parentNode ) || + context; + } + + if ( newSelector ) { + try { + push.apply( results, + newContext.querySelectorAll( newSelector ) + ); + return results; + } catch ( qsaError ) { + } finally { + if ( nid === expando ) { + context.removeAttribute( "id" ); + } + } + } + } + } + } + + // All others + return select( selector.replace( rtrim, "$1" ), context, results, seed ); +} + +/** + * Create key-value caches of limited size + * @returns {function(string, object)} Returns the Object data after storing it on itself with + * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength) + * deleting the oldest entry + */ +function createCache() { + var keys = []; + + function cache( key, value ) { + // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + if ( keys.push( key + " " ) > Expr.cacheLength ) { + // Only keep the most recent entries + delete cache[ keys.shift() ]; + } + return (cache[ key + " " ] = value); + } + return cache; +} + +/** + * Mark a function for special use by Sizzle + * @param {Function} fn The function to mark + */ +function markFunction( fn ) { + fn[ expando ] = true; + return fn; +} + +/** + * Support testing using an element + * @param {Function} fn Passed the created element and returns a boolean result + */ +function assert( fn ) { + var el = document.createElement("fieldset"); + + try { + return !!fn( el ); + } catch (e) { + return false; + } finally { + // Remove from its parent by default + if ( el.parentNode ) { + el.parentNode.removeChild( el ); + } + // release memory in IE + el = null; + } +} + +/** + * Adds the same handler for all of the specified attrs + * @param {String} attrs Pipe-separated list of attributes + * @param {Function} handler The method that will be applied + */ +function addHandle( attrs, handler ) { + var arr = attrs.split("|"), + i = arr.length; + + while ( i-- ) { + Expr.attrHandle[ arr[i] ] = handler; + } +} + +/** + * Checks document order of two siblings + * @param {Element} a + * @param {Element} b + * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b + */ +function siblingCheck( a, b ) { + var cur = b && a, + diff = cur && a.nodeType === 1 && b.nodeType === 1 && + a.sourceIndex - b.sourceIndex; + + // Use IE sourceIndex if available on both nodes + if ( diff ) { + return diff; + } + + // Check if b follows a + if ( cur ) { + while ( (cur = cur.nextSibling) ) { + if ( cur === b ) { + return -1; + } + } + } + + return a ? 1 : -1; +} + +/** + * Returns a function to use in pseudos for input types + * @param {String} type + */ +function createInputPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return name === "input" && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for buttons + * @param {String} type + */ +function createButtonPseudo( type ) { + return function( elem ) { + var name = elem.nodeName.toLowerCase(); + return (name === "input" || name === "button") && elem.type === type; + }; +} + +/** + * Returns a function to use in pseudos for :enabled/:disabled + * @param {Boolean} disabled true for :disabled; false for :enabled + */ +function createDisabledPseudo( disabled ) { + // Known :disabled false positives: + // IE: *[disabled]:not(button, input, select, textarea, optgroup, option, menuitem, fieldset) + // not IE: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable + return function( elem ) { + + // Check form elements and option elements for explicit disabling + return "label" in elem && elem.disabled === disabled || + "form" in elem && elem.disabled === disabled || + + // Check non-disabled form elements for fieldset[disabled] ancestors + "form" in elem && elem.disabled === false && ( + // Support: IE6-11+ + // Ancestry is covered for us + elem.isDisabled === disabled || + + // Otherwise, assume any non-