├── .gitignore ├── Data ├── DemoFont.ufo │ ├── fontinfo.plist │ ├── glyphs │ │ ├── A_.glif │ │ ├── B_.glif │ │ ├── F_.glif │ │ ├── F__A__B_.glif │ │ ├── G_.glif │ │ ├── O_.glif │ │ ├── R_.glif │ │ ├── a#condensed_bold.glif │ │ ├── a#condensed_light.glif │ │ ├── a#wide_bold.glif │ │ ├── a#wide_light.glif │ │ ├── a.glif │ │ ├── contents.plist │ │ ├── testglyph1.glif │ │ └── testglyph1.reversed.glif │ └── metainfo.plist └── template_FoundrySettings.plist ├── Docs ├── .gitignore ├── Examples │ ├── howtos │ │ ├── buildingAccents_00.py │ │ ├── buildingAccents_01.py │ │ ├── buildingAccents_02.py │ │ ├── fontlabRemote_00.py │ │ ├── fontlabRemote_01.py │ │ ├── fontlabRemote_02.py │ │ ├── fontlabRemote_03.py │ │ ├── generatingFonts_00.py │ │ ├── glifNames_00.py │ │ ├── glyphMath_00.py │ │ ├── interpolate_00.py │ │ ├── interpolate_01.py │ │ ├── interpolate_02.py │ │ ├── kerning_00.py │ │ ├── lowLevel_00.py │ │ ├── makeUFO_00.py │ │ ├── otFeatures_00.py │ │ ├── otFeatures_01.py │ │ ├── pens_00.py │ │ ├── pens_01.py │ │ ├── pens_02.py │ │ ├── pens_03.py │ │ ├── pens_04.py │ │ ├── pens_05.py │ │ ├── pens_06.py │ │ ├── scripting_00.py │ │ ├── scripting_01.py │ │ ├── scripting_02.py │ │ ├── transformations_00.py │ │ ├── understandingContours_00.py │ │ ├── understandingContours_02.py │ │ └── understandingContours_03.py │ ├── objects │ │ ├── RAnchor_00.py │ │ ├── RAnchor_01.py │ │ ├── RComponent_00.py │ │ ├── RComponent_01.py │ │ ├── RContour_00.py │ │ ├── RFont_00.py │ │ ├── RFont_01.py │ │ ├── RFont_02.py │ │ ├── RFont_03.py │ │ ├── RFont_04.py │ │ ├── RFont_05.py │ │ ├── RGlyph_00.py │ │ ├── RGlyph_01.py │ │ ├── RGlyph_02.py │ │ ├── RGlyph_03.py │ │ ├── RInfo_00.py │ │ ├── RKerning_00.py │ │ ├── RLib_00.py │ │ ├── RPoint_00.py │ │ ├── RSegment_00.py │ │ ├── RSegment_01.py │ │ ├── RSegment_02.py │ │ ├── bPoint_00.py │ │ ├── bPoint_01.py │ │ ├── pen_00.py │ │ ├── psHints_00.py │ │ ├── psHints_01.py │ │ ├── psHints_02.py │ │ └── psHints_03.py │ └── talks │ │ ├── interpol_00.py │ │ ├── interpol_01.py │ │ ├── interpol_02.py │ │ ├── interpol_03.py │ │ ├── interpol_04.py │ │ ├── interpol_05.py │ │ ├── interpol_06.py │ │ ├── interpol_07.py │ │ ├── interpol_08.py │ │ ├── interpol_09.py │ │ ├── nonelab_00.py │ │ ├── session1_00.py │ │ ├── session1_01.py │ │ ├── session1_02.py │ │ ├── session1_03.py │ │ ├── session1_04.py │ │ ├── session1_05.py │ │ ├── session1_06.py │ │ ├── session1_07.py │ │ ├── session1_08.py │ │ ├── session1_09.py │ │ ├── session2_00.py │ │ ├── session2_01.py │ │ ├── session2_02.py │ │ ├── session2_03.py │ │ ├── session2_04.py │ │ ├── session2_05.py │ │ ├── session2_06.py │ │ ├── session2_07.py │ │ ├── session2_08.py │ │ ├── session2_09.py │ │ ├── session2_10.py │ │ ├── session2_11.py │ │ ├── session3_00.py │ │ ├── session3_01.py │ │ ├── session3_02.py │ │ ├── session3_03.py │ │ ├── session3_04.py │ │ ├── session3_05.py │ │ ├── session6_00.py │ │ ├── session6_01.py │ │ ├── session6_02.py │ │ ├── session6_03.py │ │ ├── session6_04.py │ │ ├── session6_05.py │ │ ├── session6_06.py │ │ ├── session6_07.py │ │ ├── session6_08.py │ │ ├── session6_09.py │ │ ├── session6_10.py │ │ ├── session6_11.py │ │ └── session6_12.py ├── Makefile ├── README.md ├── _themes │ └── roboFabTheme │ │ ├── .gitignore │ │ ├── layout.html │ │ ├── relations.html │ │ ├── search.html │ │ ├── searchbox.html │ │ ├── static │ │ ├── _img │ │ │ ├── drawmodel.jpg │ │ │ ├── drawmodel_header.jpg │ │ │ ├── logo.gif │ │ │ ├── offdrawmodel_02.gif │ │ │ ├── offdrawmodel_05.gif │ │ │ ├── offdrawmodel_07.gif │ │ │ ├── offdrawmodel_11.gif │ │ │ ├── offdrawmodel_13.gif │ │ │ ├── offdrawmodel_17.gif │ │ │ ├── offdrawmodel_20.gif │ │ │ ├── offdrawmodel_22.gif │ │ │ ├── offdrawmodel_26.gif │ │ │ ├── offdrawmodel_28.gif │ │ │ ├── offdrawmodel_30.gif │ │ │ ├── offdrawmodel_34.gif │ │ │ ├── ondrawmodel_02.gif │ │ │ ├── ondrawmodel_05.gif │ │ │ ├── ondrawmodel_07.gif │ │ │ ├── ondrawmodel_11.gif │ │ │ ├── ondrawmodel_13.gif │ │ │ ├── ondrawmodel_17.gif │ │ │ ├── ondrawmodel_20.gif │ │ │ ├── ondrawmodel_22.gif │ │ │ ├── ondrawmodel_26.gif │ │ │ ├── ondrawmodel_28.gif │ │ │ ├── ondrawmodel_30.gif │ │ │ └── ondrawmodel_34.gif │ │ ├── robofab.css │ │ ├── robofab.sass │ │ └── sass2css.py │ │ └── theme.conf ├── build-docs.py ├── build-extension.py ├── docs.py ├── images │ ├── ObjectModel.svg │ ├── RAnchor.gif │ ├── RComponent.gif │ ├── RContour.gif │ ├── RFont.gif │ ├── RGlyph.gif │ ├── RInfo.gif │ ├── RKerning.gif │ ├── RPoint.gif │ ├── RSegment.gif │ ├── askstring_mac.jpg │ ├── askyesnocancel_mac.jpg │ ├── bPoint.gif │ ├── cent.gif │ ├── compatibility-scheme_2_01.gif │ ├── compatibility-scheme_2_02.gif │ ├── compatibility-scheme_2_03.gif │ ├── compatibility-scheme_2_04.gif │ ├── compatibility-scheme_2_05.gif │ ├── compatibility-scheme_2_06.gif │ ├── compatibility-scheme_2_07.gif │ ├── compatibility-scheme_2_08.gif │ ├── condensor.jpg │ ├── contours.jpg │ ├── contours_bpoints.jpg │ ├── contours_points.jpg │ ├── contours_segments.jpg │ ├── contours_segments_points.jpg │ ├── drawingexample.jpg │ ├── drawmodel.jpg │ ├── exportmenu.gif │ ├── findglyph_fl.jpg │ ├── flatten.gif │ ├── fontLib.gif │ ├── glyphLib.gif │ ├── glyphinterpol.gif │ ├── glyphmath_examples_01.gif │ ├── glyphmath_examples_02.gif │ ├── glyphmath_examples_03.gif │ ├── glyphmath_examples_04.gif │ ├── glyphmath_examples_05.gif │ ├── halftone.gif │ ├── logo.gif │ ├── message_mac.jpg │ ├── rasteriser.gif │ ├── selectfont_fl.jpg │ ├── selectglyph_fl.jpg │ ├── spike.gif │ ├── threshold.gif │ └── ufo.jpg └── source │ ├── api │ ├── gString.rst │ ├── glifLib.rst │ ├── glifLib2.rst │ ├── index.rst │ ├── interface │ │ ├── all │ │ │ ├── all.rst │ │ │ ├── dialogs.rst │ │ │ ├── dialogs_default.rst │ │ │ ├── dialogs_fontlab_legacy1.rst │ │ │ ├── dialogs_fontlab_legacy2.rst │ │ │ ├── dialogs_legacy.rst │ │ │ └── dialogs_mac_vanilla.rst │ │ ├── interface.rst │ │ ├── mac │ │ │ └── mac.rst │ │ └── win │ │ │ └── win.rst │ ├── misc │ │ ├── arrayTools.rst │ │ ├── bezierTools.rst │ │ ├── misc.rst │ │ ├── speedTestCase.rst │ │ └── test.rst │ ├── objects │ │ ├── index.rst │ │ ├── objectsBase.rst │ │ ├── objectsFF.rst │ │ ├── objectsFL.rst │ │ └── objectsRF.rst │ ├── pens │ │ ├── adapterPens.rst │ │ ├── angledMarginPen.rst │ │ ├── boundsPen.rst │ │ ├── digestPen.rst │ │ ├── filterPen.rst │ │ ├── flPen.rst │ │ ├── marginPen.rst │ │ ├── mathPens.rst │ │ ├── pens.rst │ │ ├── pointPen.rst │ │ ├── quartzPen.rst │ │ ├── reverseContourPointPen.rst │ │ └── rfUFOPen.rst │ ├── plistFromTree.rst │ ├── plistlib.rst │ ├── test │ │ ├── test.rst │ │ ├── test_dialogs.rst │ │ ├── test_glifLib.rst │ │ ├── test_noneLabUFOReadWrite.rst │ │ ├── test_objectsUFO.rst │ │ ├── test_pens.rst │ │ └── test_psHints.rst │ ├── tools │ │ ├── accentBuilder.rst │ │ ├── fontlabFeatureSplitter.rst │ │ ├── glifExport.rst │ │ ├── glifImport.rst │ │ ├── glyphConstruction.rst │ │ ├── glyphNameSchemes.rst │ │ ├── index.rst │ │ ├── objectDumper.rst │ │ ├── otFeatures.rst │ │ ├── proof.rst │ │ ├── remote.rst │ │ ├── rfPrefs.rst │ │ ├── toolsAll.rst │ │ ├── toolsFL.rst │ │ └── toolsRF.rst │ ├── ufoLib.rst │ ├── world.rst │ └── xmlTreeBuilder.rst │ ├── conf.py │ ├── howtos │ ├── building_accents.rst │ ├── fontlab_remote.rst │ ├── generating_fonts.rst │ ├── glifnames.rst │ ├── glyphmath.rst │ ├── index.rst │ ├── interpolate.rst │ ├── lowlevel.rst │ ├── makeufo.rst │ ├── ot_features.rst │ ├── scripting.rst │ ├── understanding_contours.rst │ ├── use_lib.rst │ ├── use_pens.rst │ ├── use_transformations.rst │ └── world.rst │ ├── index.rst │ ├── intro │ ├── dialogs.rst │ ├── download.rst │ ├── gettingstarted.rst │ ├── glossary.rst │ ├── history.rst │ ├── index.rst │ ├── install.rst │ ├── intro.rst │ ├── limitations.rst │ ├── links.rst │ ├── summary.rst │ ├── tools.rst │ └── ufo.rst │ ├── objects │ ├── RAnchor.rst │ ├── RComponent.rst │ ├── RContour.rst │ ├── RFont.rst │ ├── RGlyph.rst │ ├── RInfo.rst │ ├── RKerning.rst │ ├── RPoint.rst │ ├── RSegment.rst │ ├── bPoint.rst │ ├── index.rst │ ├── libs.rst │ ├── model.rst │ ├── objects.rst │ ├── pens.rst │ ├── psHints.rst │ └── psHintsGlyph.rst │ └── talks │ ├── dialogkit.rst │ ├── editors.rst │ ├── index.rst │ ├── interpolation.rst │ ├── python_basics.rst │ ├── session1.rst │ ├── session2.rst │ ├── session3.rst │ ├── session4.rst │ └── session6.rst ├── LICENSE.txt ├── Lib └── robofab │ ├── __init__.py │ ├── contrib │ └── __init__.py │ ├── gString.py │ ├── glifLib.py │ ├── glifLib2.py │ ├── interface │ ├── __init__.py │ ├── all │ │ ├── __init__.py │ │ ├── dialogs.py │ │ ├── dialogs_default.py │ │ ├── dialogs_fontlab_legacy1.py │ │ ├── dialogs_fontlab_legacy2.py │ │ ├── dialogs_legacy.py │ │ └── dialogs_mac_vanilla.py │ ├── mac │ │ ├── __init__.py │ │ └── getFileOrFolder.py │ └── win │ │ └── __init__.py │ ├── misc │ ├── __init__.py │ ├── arrayTools.py │ ├── bezierTools.py │ ├── speedTestCase.py │ └── test.py │ ├── objects │ ├── __init__.py │ ├── objectsBase.py │ ├── objectsFF.py │ ├── objectsFL.py │ └── objectsRF.py │ ├── path │ ├── __init__.py │ └── intersect.py │ ├── pens │ ├── __init__.py │ ├── adapterPens.py │ ├── angledMarginPen.py │ ├── boundsPen.py │ ├── digestPen.py │ ├── filterPen.py │ ├── flPen.py │ ├── marginPen.py │ ├── mathPens.py │ ├── pointPen.py │ ├── quartzPen.py │ ├── reverseContourPointPen.py │ └── rfUFOPen.py │ ├── plistFromTree.py │ ├── plistlib.py │ ├── test │ ├── __init__.py │ ├── runAll.py │ ├── testSupport.py │ ├── test_RInfoFL.py │ ├── test_RInfoRF.py │ ├── test_dialogs.py │ ├── test_fontLabUFOReadWrite.py │ ├── test_glifLib.py │ ├── test_noneLabUFOReadWrite.py │ ├── test_objectsFL.py │ ├── test_objectsUFO.py │ ├── test_pens.py │ ├── test_psHints.py │ └── test_ufoLib.py │ ├── tools │ ├── __init__.py │ ├── accentBuilder.py │ ├── fontlabFeatureSplitter.py │ ├── glifExport.py │ ├── glifImport.py │ ├── glyphConstruction.py │ ├── glyphNameSchemes.py │ ├── objectDumper.py │ ├── otFeatures.py │ ├── proof.py │ ├── remote.py │ ├── rfPrefs.py │ ├── toolsAll.py │ ├── toolsFL.py │ └── toolsRF.py │ ├── ufoLib.py │ ├── world.py │ └── xmlTreeBuilder.py ├── README.md ├── Scripts ├── Contributed │ ├── FontLabTokenize.py │ ├── LICENSE.txt │ └── ReadMe.txt ├── ReadMe.txt ├── RoboFabIntro │ ├── demo_AlignBPoints.py │ ├── demo_CorrectDirection.py │ ├── demo_FindCompatibleGlyphs.py │ ├── demo_GlyphAppender.py │ ├── demo_GlyphMath.py │ ├── demo_InterpolPreview.py │ ├── demo_InvertSelectedSegments.py │ ├── demo_MakeCameoFont.py │ ├── demo_PrintKerningCounts.py │ ├── demo_PrintMeasuments.py │ ├── demo_RoundKerning.py │ ├── demo_UFORemoveOverlap.py │ ├── intro_008.py │ ├── intro_AccentBuilder.py │ ├── intro_ContoursSegmentsPoints.py │ ├── intro_FontAndGlyphLib.py │ ├── intro_FontObject.py │ ├── intro_FoundrySettings.py │ ├── intro_GeneratingFonts.py │ ├── intro_GlyphObject.py │ ├── intro_GlyphProperties.py │ ├── intro_Groups.py │ ├── intro_InterpolateFonts.py │ ├── intro_Kerning.py │ ├── intro_SimpleDrawing.py │ ├── intro_StartHere.py │ └── postScriptHintData.py ├── RoboFabUFO │ ├── ExportAllOpenFontsAsUFO.py │ ├── ExportFontToUFO.py │ ├── ExportOneGlyphToGlif.py │ ├── ExportOneGlyphToUFO.py │ ├── ExportSelectedGlyphsToUFO.py │ ├── ExportSelectedGlyphsToUFOForAllFonts.py │ ├── ImportChangedGlyphsFromUFO.py │ ├── ImportFontFromUFO.py │ ├── ImportOneGlyphFromUFO.py │ ├── ImportUFOBatch.py │ ├── SelectedGlyphsToUFO.py │ ├── SelectedGlyphsToUFOForAllFonts.py │ └── UpdateFromUFO.py └── RoboFabUtils │ ├── FontToUfo.py │ ├── GenerateKernProof.py │ ├── RewriteDemoFont.py │ ├── RobustBatchGenerate.py │ ├── Start_FL_Remote.py │ └── TestFontEquality.py ├── TestData ├── TestFont1 (UFO1).ufo │ ├── fontinfo.plist │ ├── glyphs │ │ ├── A_.glif │ │ ├── B_.glif │ │ └── contents.plist │ ├── groups.plist │ ├── kerning.plist │ ├── lib.plist │ └── metainfo.plist ├── TestFont1 (UFO2).ufo │ ├── features.fea │ ├── fontinfo.plist │ ├── glyphs │ │ ├── A_.glif │ │ ├── B_.glif │ │ └── contents.plist │ ├── groups.plist │ ├── kerning.plist │ ├── lib.plist │ └── metainfo.plist └── TestFont1.vfb ├── Tools ├── autoDistroBuilder.py ├── buildRoboFabDistroFromSVN.py ├── installFontLab │ ├── __init__.py │ ├── installerFunctions.py │ ├── installerScript.py │ ├── pythonInspector.py │ └── testData │ │ └── dummyModules │ │ ├── testModule1 │ │ └── Lib │ │ │ └── testModule1 │ │ │ └── __init__.py │ │ └── testModule2 │ │ └── Lib │ │ └── testModule2 │ │ └── __init__.py ├── installModuleForFontLabOSX.py └── versionSniffer.py ├── install.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pyc 3 | build/ -------------------------------------------------------------------------------- /Data/DemoFont.ufo/glyphs/A_.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /Data/DemoFont.ufo/glyphs/B_.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Data/DemoFont.ufo/glyphs/F_.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Data/DemoFont.ufo/glyphs/F__A__B_.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Data/DemoFont.ufo/glyphs/G_.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /Data/DemoFont.ufo/glyphs/O_.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /Data/DemoFont.ufo/glyphs/R_.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /Data/DemoFont.ufo/glyphs/a.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Data/DemoFont.ufo/glyphs/contents.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | A 6 | A_.glif 7 | B 8 | B_.glif 9 | F 10 | F_.glif 11 | F_A_B 12 | F__A__B_.glif 13 | G 14 | G_.glif 15 | O 16 | O_.glif 17 | R 18 | R_.glif 19 | a 20 | a.glif 21 | a#condensed_bold 22 | a#condensed_bold.glif 23 | a#condensed_light 24 | a#condensed_light.glif 25 | a#wide_bold 26 | a#wide_bold.glif 27 | a#wide_light 28 | a#wide_light.glif 29 | testglyph1 30 | testglyph1.glif 31 | testglyph1.reversed 32 | testglyph1.reversed.glif 33 | 34 | 35 | -------------------------------------------------------------------------------- /Data/DemoFont.ufo/glyphs/testglyph1.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Data/DemoFont.ufo/glyphs/testglyph1.reversed.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Data/DemoFont.ufo/metainfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | creator 6 | org.robofab.ufoLib 7 | formatVersion 8 | 1 9 | 10 | 11 | -------------------------------------------------------------------------------- /Data/template_FoundrySettings.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | copyright 6 | (C) RoboFab Type Foundry 7 | designer 8 | Rob O. Fab 9 | designerurl 10 | http://www.afontdesigner.com 11 | license 12 | RoboFab demo EULA 13 | licenseurl 14 | (C) RoboFab Type Foundry 15 | notice 16 | (C) RoboFab Type Foundry 17 | trademark 18 | RoboFab is a trademark of RoboFab 19 | ttvendor 20 | PYRS 21 | vendorurl 22 | http://www.myfoundry.com 23 | 24 | 25 | -------------------------------------------------------------------------------- /Docs/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .roboFontExt 3 | *.pyc 4 | _build/ -------------------------------------------------------------------------------- /Docs/Examples/howtos/buildingAccents_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Buildingaccents howto 3 | # usage examples 4 | 5 | from robofab.world import CurrentFont 6 | 7 | f = CurrentFont() 8 | f.newGlyph("aacute") 9 | f["aacute"].appendComponent("a") 10 | f["aacute"].appendComponent("acute", (200, 0)) 11 | f["aacute"].width = f["a"].width 12 | f.update() -------------------------------------------------------------------------------- /Docs/Examples/howtos/buildingAccents_01.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Buildingaccents howto 3 | # AccentBuilder examples 4 | 5 | from robofab.world import CurrentFont 6 | from robofab.accentBuilder import AccentTools, buildRelatedAccentList 7 | 8 | font = CurrentFont() 9 | 10 | # a list of accented glyphs that you want to build 11 | myList = ['Aacute', 'aacute'] 12 | 13 | # search for glyphs related to glyphs in myList and add them to myList 14 | myList = buildRelatedAccentList(font, myList)+myList 15 | 16 | # start the class 17 | at = AccentTools(font, myList) 18 | 19 | # clear away any anchors that exist (this is optional) 20 | at.clearAnchors() 21 | 22 | # add necessary anchors if you want to 23 | at.buildAnchors(ucXOffset=20, ucYOffset=40, lcXOffset=15, lcYOffset=30) 24 | 25 | # print a report of any errors that occured 26 | at.printAnchorErrors() 27 | 28 | # build the accented glyphs if you want to 29 | at.buildAccents() 30 | 31 | # print a report of any errors that occured 32 | at.printAccentErrors() -------------------------------------------------------------------------------- /Docs/Examples/howtos/buildingAccents_02.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Buildingaccents howto 3 | # attribute examples 4 | 5 | # a script to generate all necessary accented characters. 6 | # this assumes all anchor points are set correctly. 7 | # including doublelayer accents. so, add anchorpoints 8 | # on the accents too! 9 | # (c) evb 10 | 11 | from robofab.world import CurrentFont 12 | from robofab.tools.toolsAll import readGlyphConstructions 13 | 14 | f = CurrentFont() 15 | 16 | import string 17 | 18 | theList = [ 19 | # caps 20 | 'AEacute', 21 | 'AEmacron', 22 | 'Aacute', 23 | 'Abreve', 24 | # add all the accents you want in this list 25 | ] 26 | 27 | con = readGlyphConstructions() 28 | theList.sort() 29 | 30 | def accentify(f, preflight=False): 31 | print 'start accentification', f.info.fullName 32 | slots = con.keys() 33 | slots.sort() 34 | for k in theList: 35 | if k[-3:] in [".sc"]: 36 | isSpecial = True 37 | tag = k[-3:] 38 | name = k[:-3] 39 | else: 40 | isSpecial = False 41 | tag = "" 42 | name = k 43 | parts = con.get(name, None) 44 | if parts is None: 45 | print k, "not defined?" 46 | continue 47 | base = parts[0] 48 | accents = parts[1:] 49 | f.generateGlyph(k, preflight=preflight) 50 | f[k].mark = 100 + randint(-20, 20) 51 | f[k].autoUnicodes() 52 | f[k].update() 53 | f.update() 54 | 55 | accentify(f) 56 | print 'done' 57 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/fontlabRemote_00.py: -------------------------------------------------------------------------------- 1 | # start the remote stuff in FontLab 2 | import robofab.tools.remote 3 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/fontlabRemote_01.py: -------------------------------------------------------------------------------- 1 | # first, try a bit of python code 2 | from robofab.tools.remote import runFontLabRemote 3 | print runFontLabRemote("print 1+1") -------------------------------------------------------------------------------- /Docs/Examples/howtos/fontlabRemote_02.py: -------------------------------------------------------------------------------- 1 | from robofab.tools.remote import transmitGlyph 2 | 3 | # Pick a UFO font: 4 | f = OpenFont() 5 | 6 | # one to beam up, Scotty! 7 | transmitGlyph(f['n']) 8 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/fontlabRemote_03.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Fontlabremote howto 3 | # usage examples 4 | 5 | #FLM: Remove overlap from Remote Glyph. 6 | 7 | from robofab.world import OpenFont 8 | from robofab.tools.remote import transmitGlyph, receiveGlyph, runFontLabRemote 9 | 10 | # Pick a UFO font: 11 | f = OpenFont() 12 | 13 | print "Number of contours before", len(f['A']) 14 | 15 | # call FontLab to make a new font 16 | startNewFontCode = """from robofab.world import NewFont 17 | f = NewFont() 18 | f.info.fullName = 'Temporary Font generated by RoboFab Remote'""" 19 | 20 | print runFontLabRemote(startNewFontCode) 21 | 22 | # send a glyph to FontLab, 23 | # it will be inserted in the CurrentFont. 24 | transmitGlyph(f['A']) 25 | f.removeGlyph('A') 26 | 27 | # send instructions to remove overlap for this glyph 28 | overlapCode = """from robofab.world import CurrentFont 29 | from robofab.tools.remote import transmitGlyph 30 | f = CurrentFont() 31 | f["A"].removeOverlap() 32 | f.update() 33 | transmitGlyph(f['A']) 34 | """ 35 | 36 | # send the code and catch the output 37 | x = runFontLabRemote(overlapCode) 38 | # interpret the output 39 | receiveGlyph(x, f) 40 | print "Number of contours after: ", len(f['A']) 41 | 42 | # send instructions to FontLab to close the font again. 43 | closeFontCode = """from robofab.world import CurrentFont 44 | f = CurrentFont() 45 | f.close(None) 46 | """ 47 | print runFontLabRemote(closeFontCode) 48 | print 'done!' 49 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/generatingFonts_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Generatefonts howto 3 | # usage examples 4 | 5 | import os.path 6 | from robofab.world import CurrentFont 7 | 8 | font = CurrentFont() 9 | path = font.path 10 | dir, fileName = os.path.split(path) 11 | path = os.sep.join([dir, font.info.fullName]) 12 | font.generate('mactype1', path) 13 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/glifNames_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Glifnames howto 3 | # glyphNameToShortFileName examples 4 | 5 | # examples of glyphname to glif name transformations 6 | from robofab.tools.glyphNameSchemes import glyphNameToShortFileName 7 | 8 | # a short name 9 | print glyphNameToShortFileName("accent", None) 10 | 11 | # a short name, starting with capital letter 12 | print glyphNameToShortFileName("Accent", None) 13 | 14 | # a really long name - note the hexadecimal hash at the end 15 | print glyphNameToShortFileName("this_is_a_very_long_glyph_name.altswash2", None) 16 | 17 | # a name with a period in it, 1 18 | print glyphNameToShortFileName("a.alt", None) 19 | 20 | # a name with a period in it, 2 21 | print glyphNameToShortFileName(".notdef", None) 22 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/glyphMath_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Glyphmath howto 3 | # Fun examples 4 | 5 | #FLM: Fun with GlyphMath 6 | 7 | # this example is meant to run with the RoboFab Demo Font 8 | # as the Current Font. So, if you're doing this in FontLab 9 | # import the Demo Font UFO first. 10 | 11 | from robofab.world import CurrentFont 12 | from random import random 13 | 14 | f = CurrentFont() 15 | condensedLight = f["a#condensed_light"] 16 | wideLight = f["a#wide_light"] 17 | wideBold = f["a#wide_bold"] 18 | 19 | diff = wideLight - condensedLight 20 | 21 | destination = f.newGlyph("a#deltaexperiment") 22 | destination.clear() 23 | x = wideBold + (condensedLight-wideLight)*random() 24 | 25 | destination.appendGlyph( x) 26 | destination.width = x.width 27 | 28 | f.update() -------------------------------------------------------------------------------- /Docs/Examples/howtos/interpolate_00.py: -------------------------------------------------------------------------------- 1 | from robofab.world import CurrentFont 2 | f = CurrentFont() 3 | a = f["a"] 4 | print a.isCompatible(f["b"], False) 5 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/interpolate_01.py: -------------------------------------------------------------------------------- 1 | from robofab.world import CurrentFont 2 | f = CurrentFont() 3 | a = f["a"] 4 | print a.isCompatible(f["b"], True) 5 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/interpolate_02.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Interpolate howto 3 | # Straight Interpolating examples 4 | 5 | from robofab.world import OpenFont 6 | minFont = OpenFont(pathToMinFont) 7 | maxFont = OpenFont(pathToMaxFont) 8 | # or any other way you like to get two font objects 9 | 10 | inbetweenFont = OpenFont(pathToInbetweenFont) 11 | # so now we have 3 font objects, right? 12 | 13 | inbetweenFont.interpolate(.5, minFont, maxFont) 14 | # presto, inbetweenFont is now 50% of one and 50% of the other 15 | 16 | inbetweenFont.interpolate((.92, .12), minFont, maxFont) 17 | # presto, inbetweenFont is now horizontally 18 | # vertically interpolated in different ways. -------------------------------------------------------------------------------- /Docs/Examples/howtos/kerning_00.py: -------------------------------------------------------------------------------- 1 | # showing where the data lives in the RoboFab objects. 2 | from robofab.world import CurrentFont 3 | 4 | f = CurrentFont() 5 | 6 | # these are pairs 7 | print f.kerning.keys() 8 | 9 | # get the value for this pair 10 | print f.kerning[('MMK_L_baseserif', 'n')] -------------------------------------------------------------------------------- /Docs/Examples/howtos/lowLevel_00.py: -------------------------------------------------------------------------------- 1 | from robofab.world import CurrentFont 2 | f = CurrentFont() 3 | # this is the high level RoboFab object 4 | print f 5 | # this is the low level FontLab object, not a part of RoboFab 6 | print f.naked() 7 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/makeUFO_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Makeufo howto 3 | # Makeufo from a font binary examples 4 | 5 | from robofab.tools.toolsAll import fontToUFO 6 | from robofab.interface.all.dialogs import GetFile, PutFile 7 | 8 | srcPath = GetFile('Select the source') 9 | dstPath = PutFile('Save as...') 10 | 11 | fontToUFO(srcPath, dstPath) 12 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/otFeatures_00.py: -------------------------------------------------------------------------------- 1 | # Getting to feature data in a UFO. 2 | 3 | from robofab.world import OpenFont 4 | 5 | path = "A/path/to/font.ufo" 6 | 7 | f = OpenFont(path) 8 | 9 | print f.lib.keys() 10 | print f.lib["com.robofab.features"] 11 | print f.lib["com.robofab.features"]['liga'] 12 | print f.lib["com.robofab.featureorder"] 13 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/otFeatures_01.py: -------------------------------------------------------------------------------- 1 | # Getting to feature data in a FontLab 2 | from robofab.world import CurrentFont 3 | 4 | f = CurrentFont() 5 | 6 | print f.naked().features 7 | 8 | # these are raw FontLab feature objects. -------------------------------------------------------------------------------- /Docs/Examples/howtos/pens_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Usepens howto 3 | # usage examples 4 | 5 | from robofab.world import CurrentFont 6 | 7 | f = CurrentFont() 8 | 9 | newGlyph = f.newGlyph('demoDrawGlyph', clear=True) 10 | newGlyph.width = 1000 11 | 12 | # hey, what's this: 13 | pen = newGlyph.getPen() 14 | # ha! a sneaky way to get a pen object! 15 | 16 | pen.moveTo((100, 100)) 17 | pen.lineTo((800, 100)) 18 | pen.curveTo((1000, 300), (1000, 600), (800, 800)) 19 | pen.lineTo((100, 800)) 20 | pen.lineTo((100, 100)) 21 | pen.closePath() 22 | 23 | newGlyph.update() 24 | 25 | f.update() -------------------------------------------------------------------------------- /Docs/Examples/howtos/pens_01.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Usepens howto 3 | # attribute examples 4 | 5 | from robofab.world import OpenFont 6 | from robofab.pens.digestPen import DigestPointPen 7 | 8 | f = OpenFont() 9 | 10 | myPen = DigestPointPen() 11 | f['period'].drawPoints(myPen) 12 | 13 | print myPen.getDigest() 14 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/pens_02.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Usepens howto 3 | # DigestPointStructurePen examples 4 | 5 | from robofab.world import OpenFont 6 | from robofab.pens.digestPen import DigestPointStructurePen 7 | 8 | f = OpenFont() 9 | 10 | myPen = DigestPointStructurePen() 11 | f['period'].drawPoints(myPen) 12 | 13 | print myPen.getDigest() 14 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/pens_03.py: -------------------------------------------------------------------------------- 1 | from robofab.world import CurrentGlyph 2 | from robofab.pens.filterPen import flattenGlyph 3 | d = 10 4 | flattenGlyph(CurrentGlyph(), d) 5 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/pens_04.py: -------------------------------------------------------------------------------- 1 | from robofab.world import CurrentGlyph 2 | from robofab.pens.filterPen import thresholdGlyph 3 | d = 10 4 | thresholdGlyph(CurrentGlyph(), d) -------------------------------------------------------------------------------- /Docs/Examples/howtos/pens_05.py: -------------------------------------------------------------------------------- 1 | from robofab.world import CurrentGlyph 2 | from robofab.pens.filterPen import spikeGlyph 3 | segmentLength = 20 4 | spikeLength = 100 5 | spikeGlyph(CurrentGlyph(), segmentLength, spikeLength) 6 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/pens_06.py: -------------------------------------------------------------------------------- 1 | from robofab.world import CurrentGlyph 2 | from robofab.pens.filterPen import halftoneGlyph 3 | halftoneGlyph(CurrentGlyph()) 4 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/scripting_00.py: -------------------------------------------------------------------------------- 1 | from robofab.world import OpenFont 2 | f = OpenFont() 3 | # hey look! an open font dialog! 4 | print f 5 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/scripting_01.py: -------------------------------------------------------------------------------- 1 | from robofab.world import OpenFont 2 | path = "MyDrive/Folder1/Work/somefile" 3 | f = OpenFont(path) 4 | # hey look! it opens the file without asking.. 5 | print f 6 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/scripting_02.py: -------------------------------------------------------------------------------- 1 | # in Fontlab: 2 | from robofab.world import CurrentFont 3 | f = CurrentFont() 4 | print f 5 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/transformations_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Usetransformations howto 3 | # usage examples 4 | 5 | from fontTools.misc.transform import Identity 6 | from robofab.world import CurrentFont 7 | 8 | m = Identity 9 | print m 10 | 11 | m = m.rotate(math.radians(20)) 12 | print m 13 | 14 | f = CurrentFont() 15 | for c in f: 16 | c.transform(m) 17 | c.update() -------------------------------------------------------------------------------- /Docs/Examples/howtos/understandingContours_00.py: -------------------------------------------------------------------------------- 1 | # take a glyph (one with outlines obviously) 2 | g = CurrentGlyph() 3 | # get to contours by index: 4 | print g[0] -------------------------------------------------------------------------------- /Docs/Examples/howtos/understandingContours_02.py: -------------------------------------------------------------------------------- 1 | # get straight to the points in a contour 2 | # through the points attribute 3 | g = CurrentGlyph() 4 | for aPt in g[0].points: 5 | print aPt 6 | -------------------------------------------------------------------------------- /Docs/Examples/howtos/understandingContours_03.py: -------------------------------------------------------------------------------- 1 | # bpoints 2 | c = CurrentGlyph() 3 | for aPt in c[0].bPoints: 4 | print aPt.anchor 5 | print aPt.bcpIn 6 | print aPt.bcpOut 7 | print aPt.type 8 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RAnchor_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Anchor object 3 | # usage examples 4 | 5 | f = CurrentFont() 6 | 7 | for g in f: 8 | if len(g.anchors) > 0: 9 | print g, g.anchors 10 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RAnchor_01.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Anchor object 3 | # attribute examples 4 | 5 | g = CurrentGlyph() 6 | 7 | if len(g.anchors) > 0: 8 | for a in g.anchors: 9 | print a.position -------------------------------------------------------------------------------- /Docs/Examples/objects/RComponent_00.py: -------------------------------------------------------------------------------- 1 | # the easiest way to get to a component 2 | # is to get one from a glyph 3 | 4 | from robofab.world import CurrentFont 5 | 6 | f = CurrentFont() 7 | g = f['adieresis'] 8 | 9 | for c in g.components: 10 | print c 11 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RComponent_01.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Component object 3 | # attribute examples 4 | 5 | print f['adieresis'].components[0].baseGlyph 6 | print f['adieresis'].components[1].baseGlyph 7 | 8 | # move the component in the base glyph 9 | f['adieresis'].components[1].offset = (100,100) 10 | 11 | # scale the component in the base glyph 12 | f['adieresis'].components[0].scale = (.5, .25) 13 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RContour_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Contour object 3 | # usage examples 4 | 5 | # take a glyph (one with outlines obviously) 6 | c = CurrentGlyph() 7 | 8 | # get to contours by index: 9 | print c[0] -------------------------------------------------------------------------------- /Docs/Examples/objects/RFont_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Font object 3 | # Usage examples 4 | 5 | # start using the current font 6 | from robofab.world import CurrentFont 7 | f = CurrentFont() 8 | 9 | # get a clean, empty new font object, 10 | # appropriate for the current environment 11 | f = robofab.world.RFont() 12 | 13 | # get an open dialog and start a new font 14 | f = OpenFont() 15 | 16 | # open the font at path 17 | f = OpenFont(path) -------------------------------------------------------------------------------- /Docs/Examples/objects/RFont_01.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Font object 3 | # Iterate through the font object to get to the glyphs. 4 | 5 | f = CurrentFont() 6 | 7 | for glyph in f: 8 | print glyph.name -------------------------------------------------------------------------------- /Docs/Examples/objects/RFont_02.py: -------------------------------------------------------------------------------- 1 | # cache the kerning object for speed 2 | 3 | from robofab.world import CurrentFont 4 | 5 | f = CurrentFont() 6 | 7 | cachedKerning = f.kerning 8 | # continue to use cachedKerning, not f.kerning. -------------------------------------------------------------------------------- /Docs/Examples/objects/RFont_03.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Font object 3 | # attribute examples 4 | # Most useful attributes of RFont 5 | # are actually stored in RFont.info 6 | 7 | f = CurrentFont() 8 | print f.info.unitsPerEm 9 | 10 | # kerning data is available in the kerning object: 11 | print f.kerning 12 | 13 | # len() gives you the "length" of the font, i.e. the number of glyphs 14 | print "glyphs in this font:", len(f) 15 | 16 | # treat a font object as a dictionary to get to the glyphs 17 | print f["A"] 18 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RFont_04.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Font object 3 | # method examples 4 | 5 | from robofab.world import CurrentFont 6 | f = CurrentFont() 7 | 8 | # the keys() method returns a list of glyphnames: 9 | print f.keys() 10 | 11 | # find unicodes for each glyph by using the postscript name: 12 | f.autoUnicodes() -------------------------------------------------------------------------------- /Docs/Examples/objects/RFont_05.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Font object 3 | # method examples, available in FontLab 4 | 5 | from robofab.world import CurrentFont 6 | f = CurrentFont() 7 | 8 | # the keys() method returns a list of glyphnames: 9 | print f.selection 10 | 11 | # generate font binaries 12 | f.generate('otfcff') 13 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RGlyph_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Glyph object 3 | # Usage examples 4 | 5 | # start using the current font 6 | from robofab.world import CurrentGlyph 7 | g = CurrentGlyph() 8 | 9 | # suppose you've done the right imports 10 | # different ways of creating glyphs 11 | # a new empty glyph object 12 | g = robofab.world.RGlyph() 13 | 14 | # a new empty fontlab glyph object 15 | g = robofab.objects.objectsFL.RGlyph() 16 | 17 | # a new empty robofab glyph object 18 | g = robofab.objects.objectsRF.RGlyph() 19 | 20 | # the easiest way to get a new glyph 21 | # is to ask a font to make you one: 22 | g = aFontObject[glyphName] 23 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RGlyph_01.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Glyph object 3 | # attribute examples 4 | 5 | from robofab.world import CurrentFont, CurrentGlyph 6 | f = CurrentFont() 7 | 8 | # create a glyph object by asking the font 9 | g = f["Adieresis"] 10 | 11 | # alternatively, create a glyph object for the current glyph 12 | g = CurrentGlyph() 13 | 14 | # get the width 15 | print g.width 16 | 17 | # get the name 18 | print g.name 19 | 20 | # a list of unicode values for this glyph. Can be more than 1! 21 | print g.unicodes 22 | 23 | # set the width 24 | g.width = 1000 25 | print g.width 26 | 27 | # get the number of contours in a glyph by getting its length 28 | print len(g) -------------------------------------------------------------------------------- /Docs/Examples/objects/RGlyph_02.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Glyph object 3 | # method examples 4 | 5 | # get a glyph object from a font 6 | f = CurrentFont() 7 | g = f["A"] 8 | print g 9 | 10 | # move the glyph 10 units to the right, and 200 units up: 11 | g = f["a"] 12 | g.move((10, 200)) -------------------------------------------------------------------------------- /Docs/Examples/objects/RGlyph_03.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Glyph object 3 | # method examples 4 | 5 | # In FontLab the baseglyph of a component can't be changed easily. 6 | # This assumes that there will only be 7 | # one component that needs to be remapped. 8 | 9 | def remapComponent(glyph, oldBaseGlyph, newBaseGlyph): 10 | foundComponent = None 11 | for component in glyph.components: 12 | if component.baseGlyph == oldBaseGlyph: 13 | foundComponent = component 14 | break 15 | if foundComponent is None: 16 | return 17 | offset = foundComponent.offset 18 | scale = foundComponent.scale 19 | glyph.removeComponent(component) 20 | glyph.appendComponent(newBaseGlyph, offset=offset, scale=scale) 21 | 22 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RInfo_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Info object 3 | # usage examples 4 | 5 | from robofab.world import CurrentFont 6 | 7 | f = CurrentFont() 8 | print f.info.postscriptFullName 9 | print f.info.openTypeNameDesigner 10 | 11 | f.info.openTypeNameDesigner = "Jan van Krimpen" 12 | print f.info.openTypeNameDesigner 13 | print f.info.openTypeOS2VendorID 14 | print f.info.unitsPerEm 15 | print f.info.xHeight 16 | print f.info.openTypeNameLicenseURL 17 | 18 | # but you can set the values as well 19 | f.info.postscriptUniqueID = 4309359 20 | f.info.openTypeNameDesigner = "Eric Gill" 21 | 22 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RKerning_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Kerning object 3 | # usage examples 4 | 5 | f = CurrentFont() 6 | print f.kerning 7 | 8 | # getting a value from the kerning dictionary 9 | print f.kerning[('V', 'A')] 10 | print f.kerning[('T', 'X')] 11 | print f.kerning.keys() 12 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RLib_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Lib object 3 | # attribute examples 4 | 5 | # RFont objects have a lib: 6 | print aFont.lib 7 | 8 | # content of the lib of a font exported from RoboFog 9 | print f.lib.keys() -------------------------------------------------------------------------------- /Docs/Examples/objects/RPoint_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Point object 3 | # usage examples 4 | 5 | contour = CurrentGlyph()[0] 6 | print contour.points[0] 7 | 8 | from random import randint 9 | for p in contour.points: 10 | p.x += randint(-10,10) 11 | p.y += randint(-10,10) 12 | 13 | contour.update() -------------------------------------------------------------------------------- /Docs/Examples/objects/RSegment_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Segment object 3 | # usage examples 4 | 5 | f = OpenFont() 6 | 7 | for g in f: 8 | for contour in g: 9 | for segment in contour: 10 | print segment 11 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RSegment_01.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Segment object 3 | # attribute examples 4 | 5 | f = OpenFont() 6 | 7 | for g in f: 8 | for contour in g: 9 | for segment in contour: 10 | print len(segment) 11 | print segment.type 12 | print segment.smooth 13 | print segment.points 14 | print segment.onCurve 15 | print segment.offCurve 16 | print segment.selected 17 | -------------------------------------------------------------------------------- /Docs/Examples/objects/RSegment_02.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Segment object 3 | # method examples 4 | 5 | f = OpenFont() 6 | 7 | for g in f: 8 | for contour in g: 9 | for segment in contour: 10 | segment.move((50, 25)) 11 | -------------------------------------------------------------------------------- /Docs/Examples/objects/bPoint_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # bPoint object 3 | # Usage examples 4 | 5 | g = CurrentGlyph() 6 | for aPt in g[0].bPoints: 7 | print aPt 8 | -------------------------------------------------------------------------------- /Docs/Examples/objects/bPoint_01.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # bPoint object 3 | # Attribute examples 4 | 5 | g = CurrentGlyph() 6 | 7 | for aPt in g[0].bPoints: 8 | print aPt.bcpIn, aPt.bcpOut, aPt.anchor 9 | -------------------------------------------------------------------------------- /Docs/Examples/objects/pen_00.py: -------------------------------------------------------------------------------- 1 | # robofab manual 2 | # Pen object 3 | # usage examples 4 | 5 | from robofab.world import CurrentGlyph 6 | 7 | newGlyph = CurrentGlyph() 8 | 9 | pen = newGlyph.getPen() 10 | 11 | # do stuff with the pen to draw in this glyph 12 | -------------------------------------------------------------------------------- /Docs/Examples/objects/psHints_00.py: -------------------------------------------------------------------------------- 1 | # example of accessing the postscript blues 2 | # data using the font.info attributes. 3 | 4 | from robofab.world import CurrentFont 5 | 6 | f = CurrentFont() 7 | 8 | print f.info.postscriptBlueValues 9 | print f.info.postscriptOtherBlues 10 | print f.info.postscriptFamilyBlues 11 | print f.info.postscriptFamilyOtherBlues 12 | -------------------------------------------------------------------------------- /Docs/Examples/objects/psHints_01.py: -------------------------------------------------------------------------------- 1 | # example of accessing the hint data, 2 | # using the font.psHints object. 3 | 4 | from robofab.world import CurrentFont 5 | 6 | f = CurrentFont() 7 | print f.psHints.asDict() 8 | -------------------------------------------------------------------------------- /Docs/Examples/objects/psHints_02.py: -------------------------------------------------------------------------------- 1 | # example of scaling the hint data. 2 | 3 | from robofab.world import CurrentFont 4 | 5 | f = CurrentFont() 6 | print f.psHints.asDict() 7 | 8 | # a math operation returns a new, unbound object 9 | ps2 = f.psHints * .5 10 | 11 | # it needs to be rounded first 12 | ps2.round() 13 | 14 | # now you can add the values to the FL object 15 | f.psHints.update(ps2) 16 | 17 | # see those zones skip! 18 | f.update() 19 | -------------------------------------------------------------------------------- /Docs/Examples/talks/interpol_00.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # interpolate two glyphs in the same font 3 | 4 | from robofab.world import CurrentFont 5 | 6 | f = CurrentFont() 7 | factor = 0.5 8 | 9 | f["C"].interpolate(factor, f["A"], f["B"]) 10 | f["C"].update() -------------------------------------------------------------------------------- /Docs/Examples/talks/interpol_01.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # interpolate two glyphs in the same font a bunch of times 3 | 4 | from robofab.world import CurrentFont 5 | 6 | f = CurrentFont() 7 | 8 | for i in range(0, 10): 9 | factor = i*.1 10 | name = "result_%f"%factor 11 | print "interpolating", name 12 | f[name].interpolate(factor, f["A"], f["B"]) 13 | 14 | f.update() -------------------------------------------------------------------------------- /Docs/Examples/talks/interpol_02.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | 3 | from robofab.world import CurrentFont 4 | 5 | # We need to import a class with a different 6 | # implementation for the glyph object. 7 | # It looks a bit odd, but this is how it is done 8 | from robofab.objects.objectsRF import RGlyph as _RGlyph 9 | 10 | f = CurrentFont() 11 | 12 | # pick two compatible glyphs as masters 13 | m1 = f["A"] 14 | m2 = f["B"] 15 | 16 | # make a new glyph object from this other glyph class 17 | g = _RGlyph() 18 | 19 | # interpolation factor which is bound to make floats 20 | oddFactor = 0.2382345 21 | 22 | # go! 23 | g.interpolate(oddFactor, m1, m2) 24 | 25 | # let's have a look at the raw results 26 | for contour in g: 27 | for pt in contour.points: 28 | print "float", pt.x, pt.y 29 | 30 | # a glyph can round itself off: 31 | g.round() 32 | 33 | # and then it looks like integers again 34 | for contour in g: 35 | for pt in contour.points: 36 | print "integer", pt.x, pt.y 37 | -------------------------------------------------------------------------------- /Docs/Examples/talks/interpol_03.py: -------------------------------------------------------------------------------- 1 | # see if "A" and "B" can interpolate 2 | from robofab.world import CurrentFont 3 | f = CurrentFont() 4 | a = f["a"] 5 | print a.isCompatible(f["b"], False) 6 | -------------------------------------------------------------------------------- /Docs/Examples/talks/interpol_04.py: -------------------------------------------------------------------------------- 1 | # see if "A" and "B" can interpolate 2 | # and find out what's wrong if you can 3 | from robofab.world import CurrentFont 4 | f = CurrentFont() 5 | a = f["a"] 6 | print a.isCompatible(f["b"], True) 7 | -------------------------------------------------------------------------------- /Docs/Examples/talks/interpol_05.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # prepare glyph for interpolation 3 | # move startpoints 4 | # fix directions 5 | # fix contour order 6 | 7 | from robofab.world import CurrentFont 8 | 9 | f = CurrentFont() 10 | glyph = f["A"] 11 | 12 | glyph.autoContourOrder() 13 | glyph.correctDirection() 14 | for c in glyph.contours: 15 | c.autoStartSegment() 16 | glyph.update() 17 | -------------------------------------------------------------------------------- /Docs/Examples/talks/interpol_06.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # interpolate two fonts 3 | 4 | from robofab.world import SelectFont, NewFont 5 | from robofab.interface.all.dialogs import AskString 6 | 7 | font1 = SelectFont("Select font 1") 8 | font2 = SelectFont("Select font 2") 9 | 10 | value = AskString("What percentage?") 11 | value = int(value) * .01 12 | 13 | destination = NewFont() 14 | 15 | # this interpolates the glyphs 16 | destination.interpolate(value, font1, font2, doProgress=True) 17 | 18 | # this interpolates the kerning 19 | # comment this line out of you're just testing 20 | destination.kerning.interpolate(font1.kerning, font2.kerning, value) 21 | 22 | destination.update() -------------------------------------------------------------------------------- /Docs/Examples/talks/interpol_07.py: -------------------------------------------------------------------------------- 1 | # glyphmath example, using glyphs in math 2 | # in the test font: two interpolatable, different glyphs 3 | # on positions A and B. 4 | 5 | from robofab.world import CurrentFont 6 | f = CurrentFont() 7 | 8 | # glyphmath 9 | a = f["A"] 10 | b = f["B"] 11 | 12 | # multiply works as scaling up 13 | d = a * 2 14 | # or 15 | d = 2 * a 16 | 17 | # note: as of robofab svn version 200, 18 | # the "as" argument in insertGlyph has changed to "name" 19 | f.insertGlyph(d, name="A.A_times_2") 20 | 21 | # division works as scaling down 22 | d = a / 2 23 | f.insertGlyph(d, name="A.A_divide_2") 24 | 25 | # addition: add coordinates of each point 26 | d = a + b 27 | f.insertGlyph(d, name="A.A_plus_B") 28 | 29 | # subtraction: subtract coordinates of each point 30 | d = a - b 31 | f.insertGlyph(d, name="A.A_minus_B") 32 | 33 | # combination: interpolation! 34 | d = a + .5 * (b-a) 35 | f.insertGlyph(d, name="A.A_interpolate_B") 36 | 37 | f.update() -------------------------------------------------------------------------------- /Docs/Examples/talks/interpol_08.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # interpolate two fonts with a series of factors. 3 | # for each factor create a new font file. 4 | 5 | import os 6 | from robofab.world import SelectFont, NewFont 7 | from robofab.interface.all.dialogs import AskString, GetFolder 8 | 9 | font1 = SelectFont("Select font 1") 10 | font2 = SelectFont("Select font 2") 11 | where = GetFolder("Select a folder to save the interpolations") 12 | 13 | instances = [ 14 | ("Light", 0), 15 | ("NotTooLight", 0.25), 16 | ("Regular", 0.5), 17 | ("Demi", 0.75), 18 | ("Medium", 1), 19 | ] 20 | 21 | for thing in instances: 22 | name, value = thing 23 | print "generating", name, value 24 | dst = NewFont() 25 | # this interpolates the glyphs 26 | dst.interpolate(value, font1, font2, doProgress=True) 27 | # this interpolates the kerning 28 | # comment this line out of you're just testing 29 | #dst.kerning.interpolate(font1.kerning, font2.kerning, value) 30 | dst.info.familyName = "MyBigFamily" 31 | dst.info.styleName = name 32 | dst.info.autoNaming() 33 | dst.update() 34 | fileName = dst.info.familyName + "-" + dst.info.styleName + ".vfb" 35 | path = os.path.join(where, fileName) 36 | print 'saving at', path 37 | dst.save(path) 38 | dst.close() 39 | -------------------------------------------------------------------------------- /Docs/Examples/talks/interpol_09.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # Get started with a condensed if you have a regular and a bold: 3 | # seperate x, y interpolation to make stems fatter 4 | # then scaling to reduce width 5 | # stems will get their original thickness 6 | 7 | from robofab.world import CurrentFont 8 | f = CurrentFont() 9 | 10 | # these are measurements you have to take 11 | # from your font. The width of a stem. 12 | 13 | lightStem = 106 14 | fatStem = 200 15 | 16 | for i in range(0, 10): 17 | factor = (i * 0.1, 0) 18 | name = "result_%f" % factor[0] 19 | scale = float(lightStem) / (lightStem + factor[0] * (fatStem - lightStem)) 20 | print factor, scale 21 | f[name].interpolate(factor, f["A"], f["B"]) 22 | f[name].scale((scale, 1)) 23 | f[name].leftMargin = f["A"].leftMargin 24 | f[name].rightMargin = f["A"].rightMargin 25 | f.update() 26 | -------------------------------------------------------------------------------- /Docs/Examples/talks/nonelab_00.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # demo of executing python in FontLab, MacOS only 3 | 4 | # this script runs in the Python IDE 5 | # it will send some python code to FontLab 6 | # FontLab will execute the python code: 7 | # it will find the current glyph and send it to our other script. 8 | 9 | from robofab.tools.remote import runFontLabRemote, receiveGlyph 10 | from robofab.world import RFont 11 | 12 | # this is what we want FontLab to do: 13 | pythonCode = """ 14 | from robofab.world import CurrentGlyph 15 | from robofab.tools.remote import transmitGlyph 16 | g = CurrentGlyph() 17 | transmitGlyph(g) 18 | """ 19 | 20 | # this the font where we'll store the glyph from FontLab 21 | destFont = RFont() 22 | 23 | result = runFontLabRemote(pythonCode) 24 | receiveGlyph(result, destFont) 25 | print destFont.keys() 26 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session1_00.py: -------------------------------------------------------------------------------- 1 | from robofab.world import CurrentFont 2 | print CurrentFont() -------------------------------------------------------------------------------- /Docs/Examples/talks/session1_01.py: -------------------------------------------------------------------------------- 1 | # open a glyph in FL first! 2 | from robofab.world import CurrentGlyph 3 | print CurrentGlyph() 4 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session1_02.py: -------------------------------------------------------------------------------- 1 | # open a couple of fonts in FL first! 2 | from robofab.world import AllFonts 3 | print AllFonts() 4 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session1_03.py: -------------------------------------------------------------------------------- 1 | # open a couple of fonts in FL first! 2 | from robofab.world import CurrentFont 3 | 4 | font = CurrentFont() 5 | print font.path 6 | print font.kerning 7 | print font.info -------------------------------------------------------------------------------- /Docs/Examples/talks/session1_04.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # getting data from the info object 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | 8 | # naming attributes 9 | print font.info.familyName 10 | print font.info.styleName 11 | print font.info.fullName 12 | 13 | # dimension attributes 14 | print font.info.unitsPerEm 15 | print font.info.ascender 16 | print font.info.descender -------------------------------------------------------------------------------- /Docs/Examples/talks/session1_05.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # setting data in the info object 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | 8 | # naming attributes 9 | font.info.familyName = "MyFamily" 10 | print font.info.familyName 11 | font.info.styleName = "Roman" 12 | print font.info.styleName 13 | font.info.fullName = font.info.familyName + '-' + font.info.styleName 14 | print font.info.fullName 15 | 16 | # dimension attributes 17 | font.info.ascender = 600 18 | print font.info.ascender 19 | font.info.descender = -400 20 | print font.info.descender 21 | 22 | font.update() -------------------------------------------------------------------------------- /Docs/Examples/talks/session1_06.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # get a particular glyph 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | 8 | font.info.familyName = "myFamilyName" 9 | font.info.styleName = "myStyleName" 10 | font.info.autoNaming() 11 | 12 | print font.info.fullName 13 | print font.info.fontName 14 | print font.info.fondName -------------------------------------------------------------------------------- /Docs/Examples/talks/session1_07.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # get a particular glyph 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | 8 | print font['A'] 9 | print font['Adieresis'] 10 | print font['two'] 11 | print font['afii12934'] -------------------------------------------------------------------------------- /Docs/Examples/talks/session1_08.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # iteration through glyphs in a font 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | 8 | print "font has %d glyphs" % len(font) 9 | 10 | for glyph in font: 11 | print glyph -------------------------------------------------------------------------------- /Docs/Examples/talks/session1_09.py: -------------------------------------------------------------------------------- 1 | # iteration through alphabetically sorted glyphnames 2 | 3 | from robofab.world import CurrentFont 4 | 5 | font = CurrentFont() 6 | print "font has %d glyphs" % len(font) 7 | 8 | # names is now a list of strings, the names of the glyphs 9 | # not the glyphs themselves! 10 | names = font.keys() 11 | 12 | # the list of names is sorted 13 | names.sort() 14 | 15 | # now we iterate through the list of names 16 | for glyphName in names: 17 | # now we ask for the glyph with glyphName 18 | print font[glyphName] 19 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_00.py: -------------------------------------------------------------------------------- 1 | # robothon 2009 2 | # set basic attributes in a glyph 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | glyph = font['A'] 8 | 9 | print glyph.name 10 | print glyph.width 11 | print glyph.leftMargin 12 | print glyph.rightMargin 13 | print glyph.box 14 | print glyph.unicode 15 | 16 | glyph.update() -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_01.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # set basic attributes in a glyph 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | glyph = font['A'] 8 | 9 | glyph.width = 200 10 | print glyph.width 11 | 12 | glyph.leftMargin = 50 13 | print glyph.leftMargin 14 | 15 | glyph.rightMargin = 50 16 | print glyph.rightMargin 17 | 18 | glyph.unicode = 666 19 | print glyph.unicode 20 | 21 | glyph.update() 22 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_02.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # use some methods to transform a glyph 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | 8 | # ask a font for a glyph by name 9 | glyph = font['A'] 10 | 11 | # now you have a glyph object 12 | # make it do stuff by calling some of its methods 13 | glyph.move((100, 75)) 14 | glyph.scale((.5, 1.5)) 15 | glyph.appendGlyph(font['B']) 16 | glyph.removeOverlap() 17 | glyph.correctDirection() 18 | glyph.update() 19 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_03.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # iterate through a glyph's contours 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | 8 | glyph = font["A"] 9 | print glyph.getParent() -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_04.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # iterate through a glyph's contours 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | glyph = font['A'] 8 | print "glyph has %d contours" % len(glyph) 9 | for contour in glyph.contours: 10 | print contour -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_05.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # get a specific contour and view it 3 | # through point, segment and bPoint structures 4 | 5 | from robofab.world import CurrentFont 6 | 7 | font = CurrentFont() 8 | glyph = font['A'] 9 | contour = glyph[0] 10 | print contour.points 11 | print countours.segments 12 | print contour.bPoints 13 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_06.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # iterate through points 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | glyph = font['A'] 8 | for p in glyph[0].points: 9 | print p.x, p.y, p.type -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_07.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # get a pen and draw something in the current glyph 3 | # what will it draw? ha! run the script and find out! 4 | 5 | from robofab.world import CurrentGlyph 6 | 7 | g = CurrentGlyph() 8 | myPen = g.getPen() 9 | 10 | # myPen is a pen object of a type meant for 11 | # constructing paths in a glyph. 12 | # So rather than use this pen with the glyph's 13 | # own draw() method, we're going to tell it 14 | # to do things ourselves. (Just like DrawBot!) 15 | print myPen 16 | 17 | myPen.moveTo((344, 645)) 18 | myPen.lineTo((647, 261)) 19 | myPen.lineTo((662, -32)) 20 | myPen.lineTo((648, -61)) 21 | myPen.lineTo((619, -61)) 22 | myPen.lineTo((352, 54)) 23 | myPen.lineTo((72, 446)) 24 | myPen.lineTo((117, 590)) 25 | myPen.lineTo((228, 665)) 26 | myPen.closePath() 27 | myPen.moveTo((99, 451)) 28 | myPen.lineTo((365, 74)) 29 | myPen.curveTo((359, 122), (376, 178), (420, 206)) 30 | myPen.curveTo((422, 203), (142, 579), (142, 579)) 31 | myPen.closePath() 32 | myPen.moveTo((631, -32)) 33 | myPen.lineTo((629, 103)) 34 | myPen.curveTo((556, 111), (524, 71), (508, 20)) 35 | myPen.closePath() 36 | 37 | g.update() -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_08.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # get a pen and use it to print the coordinates 3 | # to the output window. This is actually almost-python 4 | # code which you can use it other scripts! 5 | 6 | from robofab.world import CurrentFont 7 | from robofab.pens.pointPen import PrintingSegmentPen 8 | 9 | font = CurrentFont() 10 | glyph = font['A'] 11 | 12 | # PrintingSegmentPen won't actually draw anything 13 | # just print the coordinates to the output: 14 | pen = PrintingSegmentPen() 15 | glyph.draw(pen) 16 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_09.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # rasterise the shape in glyph "A" 3 | # and draw boxes in a new glyph named "A.silly" 4 | 5 | from robofab.world import CurrentFont, CurrentGlyph 6 | 7 | sourceGlyph = "a" 8 | 9 | f = CurrentFont() 10 | source = f[sourceGlyph] 11 | 12 | # find out how big the shape is from the glyph.box attribute 13 | xMin, yMin, xMax, yMax = source.box 14 | 15 | # create a new glyph 16 | dest = f.newGlyph(sourceGlyph+".silly") 17 | dest.width = source.width 18 | 19 | # get a pen to draw in the new glyph 20 | myPen = dest.getPen() 21 | 22 | # a function which draws a rectangle at a specified place 23 | def drawRect(pen, x, y, size=50): 24 | pen.moveTo((x-.5*size, y-.5*size)) 25 | pen.lineTo((x+.5*size, y-.5*size)) 26 | pen.lineTo((x+.5*size, y+.5*size)) 27 | pen.lineTo((x-.5*size, y+.5*size)) 28 | pen.closePath() 29 | 30 | # the size of the raster unit 31 | resolution = 30 32 | 33 | # draw from top to bottom 34 | yValues = range(yMin, yMax, resolution) 35 | yValues.reverse() 36 | 37 | # go for it! 38 | for y in yValues: 39 | for x in range(xMin, xMax, resolution): 40 | # check the source glyph is white or black at x,y 41 | if source.pointInside((x, y)): 42 | drawRect(myPen, x, y, resolution-5) 43 | # update for each line if you like the animation 44 | # otherwise move the update() out of the loop 45 | dest.update() 46 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_10.py: -------------------------------------------------------------------------------- 1 | # use a point pen 2 | 3 | from robofab.world import CurrentFont 4 | from robofab.pens.pointPen import PrintingPointPen 5 | 6 | font = CurrentFont() 7 | glyph = font['A'] 8 | 9 | pen = PrintingPointPen() 10 | glyph.drawPoints(pen) 11 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session2_11.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # Use FontLab pathfinder functionality to cut one glyph from another 3 | 4 | from robofab.world import CurrentFont 5 | 6 | f = CurrentFont() 7 | base = f["A"] 8 | cutter = f["B"] 9 | dest = f["C"] 10 | 11 | dest.clear() 12 | dest.appendGlyph(base) 13 | dest.width = base.width 14 | dest.naked().Bsubtract(cutter.naked()) 15 | dest.update() 16 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session3_00.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # work with kerning 1 3 | from robofab.world import CurrentFont 4 | font = CurrentFont() 5 | # now the kerning object is generated once 6 | kerning = font.kerning 7 | # and ready for your instructions. 8 | print kerning 9 | print len(kerning) 10 | print kerning.keys() 11 | # proceed to work with the myKerning object 12 | # this happens in the following examples too. -------------------------------------------------------------------------------- /Docs/Examples/talks/session3_01.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # work with kerning 2 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | kerning = font.kerning 8 | 9 | # calculate the average offset 10 | print kerning.getAverage() 11 | 12 | # count pairs with these glyphs 13 | print kerning.occurrenceCount(["a", "b"]) 14 | 15 | # get the maximum values 16 | print kerning.getExtremes() 17 | 18 | # count the pars 19 | print "font has %d kerning pairs" % len(kerning) 20 | 21 | # this prints all the pairs 22 | for (left, right), value in kerning.items(): 23 | print (left, right), value -------------------------------------------------------------------------------- /Docs/Examples/talks/session3_02.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # work with kerning 3 3 | # print a specific set of pairs 4 | 5 | from robofab.world import CurrentFont 6 | 7 | font = CurrentFont() 8 | kerning = font.kerning 9 | 10 | for left, right in kerning.keys(): 11 | if kerning[(left, right)] < -100: 12 | print left, right, kerning[(left, right)] -------------------------------------------------------------------------------- /Docs/Examples/talks/session3_03.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # work with kerning 4 3 | 4 | from robofab.world import CurrentFont 5 | 6 | font = CurrentFont() 7 | kerning = font.kerning 8 | 9 | for left, right in kerning.keys(): 10 | if left == "acircumflex": 11 | print left, right, kerning[(left, right)] -------------------------------------------------------------------------------- /Docs/Examples/talks/session3_04.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # building a glyph from parts 3 | # the hard way 4 | 5 | from robofab.world import CurrentFont 6 | 7 | f = CurrentFont() 8 | 9 | # make a new glyph 10 | f.newGlyph("aacute") 11 | 12 | # add the component for the base glyph, a 13 | f["aacute"].appendComponent("a") 14 | 15 | # add the component for the accent, acute 16 | # note it has an offset 17 | f["aacute"].appendComponent("acute", (200, 0)) 18 | 19 | # set the width too 20 | f["aacute"].width = f["a"].width 21 | 22 | f.update() -------------------------------------------------------------------------------- /Docs/Examples/talks/session3_05.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # Compile a new glyph from a list of accents and required anchors 3 | # Demo of multiple accents chaining together, or "stacking". 4 | # For this example you need to set up a couple of things 5 | # in your test font: 6 | # - base glyph "a", with anchor "top" and anchor "bottom" 7 | # - glyph "dieresis" with anchor "_top" and anchor "top" 8 | # - glyph "acture" with anchor "_top" 9 | # - glyph "cedilla" with anchor "_bottom" 10 | 11 | from robofab.world import CurrentFont 12 | 13 | font = CurrentFont() 14 | 15 | # this is a list of tuples 16 | # each tuple has the name of the accent as first element 17 | # and the name of the anchor which to use as the second element 18 | 19 | accentList = [("dieresis", "top"), 20 | ("acute", "top"), 21 | ("cedilla", "bottom")] 22 | 23 | # The accents are compiled in this order, so first 24 | # "dieresis" connects to "a" using "top" anchor 25 | # "acute" connects to dieresis, using the next "top" anchor 26 | 27 | font.compileGlyph("myCompiledGlyph", "a", accentList) 28 | font.update() 29 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_00.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # set font info in all fonts 3 | 4 | from robofab.world import AllFonts 5 | 6 | for font in AllFonts(): 7 | font.info.familyName = "MyFamily" 8 | font.info.ascender = 700 9 | font.info.descender = -300 10 | font.update() 11 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_01.py: -------------------------------------------------------------------------------- 1 | # robothon 2006 2 | # get info attributes for all fonts 3 | # and dump them to a text file 4 | 5 | from robofab.world import AllFonts 6 | from robofab.interface.all.dialogs import PutFile 7 | 8 | text = [] 9 | 10 | for font in AllFonts(): 11 | text.append(str(font.path)) 12 | text.append(str(font.info.familyName)) 13 | text.append(str(font.info.styleName)) 14 | text.append(str(font.info.fullName)) 15 | text.append(str(font.info.unitsPerEm)) 16 | text.append(str(font.info.ascender)) 17 | text.append(str(font.info.descender)) 18 | text.append('') 19 | 20 | text = '\n'.join(text) 21 | path = PutFile('Save file as:') 22 | if path: 23 | file = open(path, 'w') 24 | file.write(text) 25 | file.close() -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_02.py: -------------------------------------------------------------------------------- 1 | # robothon 2006 2 | # batch save as 3 | 4 | import os 5 | from robofab.world import AllFonts 6 | from robofab.interface.all.dialogs import GetFolder 7 | 8 | path = GetFolder() 9 | if path: 10 | for font in AllFonts(): 11 | fileName = os.path.basename(font.path) 12 | newPath = os.path.join(path, fileName) 13 | font.save(newPath) -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_03.py: -------------------------------------------------------------------------------- 1 | # robothon 2006 2 | # batch interpolate 3 | 4 | import os 5 | from robofab.world import SelectFont, NewFont 6 | 7 | # ask for two masters to interpolate: 8 | font1 = SelectFont("Select font 1") 9 | font2 = SelectFont("Select font 2") 10 | # these are the interpolation factors: 11 | values = [.3, .6] 12 | 13 | for value in values: 14 | # make a new font 15 | destination = NewFont() 16 | # do the interpolation 17 | destination.interpolate(value, font1, font2, doProgress=True) 18 | destination.update() 19 | # make a new path + filename for the new font to be saved at: 20 | dir = os.path.dirname(font1.path) 21 | fileName = "Demo_%d.vfb" % (1000 * value) 22 | # save at this path and close the font 23 | destination.save(os.path.join(dir, fileName)) 24 | destination.close() -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_04.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # ask for a folder 3 | # find (nested) fontlab files in the folder 4 | # open the fonts 5 | # Demonstrates: recursive function,, dialog, os module 6 | 7 | import os.path 8 | from robofab.interface.all.dialogs import GetFolder 9 | from robofab.world import OpenFont 10 | 11 | # this function looks for fontlab files in a folder 12 | def walk(someFolder, extension): 13 | extension = extension.lower() 14 | files = [] 15 | # the os module has tools to deal with 16 | # the operating system. This returns a list of names 17 | # of stuff in the folder you feed it: 18 | names = os.listdir(someFolder) 19 | for n in names: 20 | p = os.path.join(someFolder, n) 21 | # if this new thing is a folder itself, 22 | # call this function again, but now with the 23 | # new path to check that as well. This is 24 | # called recursion. 25 | if os.path.isdir(p): 26 | # add the results of the other folder 27 | # to the list 28 | files += walk(p, extension) 29 | continue 30 | # is it a file with the extension we want? 31 | # add it then! 32 | if n.lower().find(extension) <> -1: 33 | files.append(p) 34 | return files 35 | 36 | yourFolder = GetFolder("Search a folder:") 37 | if yourFolder is not None: 38 | fontPaths = walk(yourFolder, ".vfb") 39 | for path in fontPaths: 40 | OpenFont(path) 41 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_05.py: -------------------------------------------------------------------------------- 1 | # rename the selected glyphs 2 | # in the current font to .sc 3 | 4 | from robofab.world import CurrentFont 5 | f = CurrentFont() 6 | 7 | for g in f: 8 | if g.selected == 0: 9 | continue 10 | newName = g.name+".sc" 11 | print "moving", g.name, "to", newName 12 | f.insertGlyph(g, name=newName) 13 | f.removeGlyph(g.name) 14 | f.update() 15 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_06.py: -------------------------------------------------------------------------------- 1 | # robothon 2006 2 | # batch generate 3 | 4 | from robofab.world import AllFonts 5 | 6 | for font in AllFonts(): 7 | font.generate('otfcff') -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_07.py: -------------------------------------------------------------------------------- 1 | # robothon 2006 2 | # a more robust batch generator that only has one font open at the time. 3 | 4 | from robofab.interface.all.dialogs import GetFolder 5 | from robofab.world import RFont, OpenFont 6 | import os 7 | 8 | def collectSources(root): 9 | files = [] 10 | ext = ['.vfb'] 11 | names = os.listdir(root) 12 | for n in names: 13 | if os.path.splitext(n)[1] in ext: 14 | files.append(os.path.join(root, n)) 15 | return files 16 | 17 | # A little function for making folders. we'll need it later. 18 | def makeFolder(path): 19 | # if the path doesn't exist, make it! 20 | if not os.path.exists(path): 21 | os.makedirs(path) 22 | 23 | def makeDestination(root): 24 | macPath = os.path.join(root, 'FabFonts', 'ForMac') 25 | makeFolder(macPath) 26 | return macPath 27 | 28 | def generateOne(f, dstDir): 29 | print "generating %s"%f.info.fullName 30 | f.generate('otfcff', dstDir) 31 | 32 | f = GetFolder() 33 | 34 | if f is not None: 35 | paths = collectSources(f) 36 | dstDir = makeDestination(f) 37 | for f in paths: 38 | font = None 39 | print f 40 | try: 41 | font = OpenFont(f) 42 | generateOne(font, dstDir) 43 | finally: 44 | if font is not None: 45 | font.close(False) 46 | print 'done' 47 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_08.py: -------------------------------------------------------------------------------- 1 | # robothon 2006 2 | # merge two fonts 3 | 4 | from robofab.world import SelectFont, NewFont 5 | from robofab.pens.digestPen import DigestPointPen 6 | from sets import Set 7 | 8 | font1 = SelectFont("Select base font") 9 | font2 = SelectFont("Select alternate font") 10 | 11 | font1Names = Set(font1.keys()) 12 | font2Names = Set(font2.keys()) 13 | 14 | commonNames = font1Names & font2Names 15 | uncommonNames = font2Names - font1Names 16 | 17 | for glyphName in commonNames: 18 | glyph1 = font1[glyphName] 19 | pointPen = DigestPointPen() 20 | glyph1.drawPoints(pointPen) 21 | digest1 = pointPen.getDigest() 22 | 23 | glyph2 = font2[glyphName] 24 | pointPen = DigestPointPen() 25 | glyph2.drawPoints(pointPen) 26 | digest2 = pointPen.getDigest() 27 | 28 | if digest1 != digest2: 29 | print '> alt >', glyphName 30 | glyph3 = font1.insertGlyph(glyph2, name=glyphName+'.alt') 31 | glyph3.mark = 1 32 | glyph3.update() 33 | 34 | for glyphName in uncommonNames: 35 | print '>', glyphName 36 | glyph = font1.insertGlyph(font2[glyphName]) 37 | glyph.mark = 60 38 | glyph.update() 39 | 40 | font1.update() -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_09.py: -------------------------------------------------------------------------------- 1 | # show the objects from the fontlab layer 2 | 3 | from robofab.world import CurrentFont 4 | 5 | f = CurrentFont() 6 | print f.naked() 7 | 8 | g = f["A"] 9 | print g.naked() 10 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_10.py: -------------------------------------------------------------------------------- 1 | # show vhints for current glyph 2 | g = CurrentGlyph() 3 | g.naked().vhints 4 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_11.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # show OpenType naming records 3 | # in the fontlab API 4 | 5 | from robofab.world import CurrentFont 6 | 7 | f = CurrentFont() 8 | fn = f.naked() 9 | 10 | for r in fn.fontnames: 11 | print r.nid, r.pid, r.eid, r.lid, r.name 12 | -------------------------------------------------------------------------------- /Docs/Examples/talks/session6_12.py: -------------------------------------------------------------------------------- 1 | # robothon06 2 | # show encoding 3 | 4 | from robofab.world import CurrentFont 5 | 6 | f = CurrentFont() 7 | fn = f.naked() 8 | 9 | # object containing encoding records. 10 | # you can iterate through it by using an index. 11 | print fn.encoding 12 | 13 | for i in range(len(fn.encoding)): 14 | er = fn.encoding[i] 15 | print er, er.name, er.unicode 16 | -------------------------------------------------------------------------------- /Docs/README.md: -------------------------------------------------------------------------------- 1 | RoboFab Documentation 2 | ===================== 3 | 4 | The complete RoboFab documentation, ported to Sphinx. 5 | 6 | - Introduction 7 | - Objects 8 | - How To’s 9 | - Step-by-step 10 | - Examples 11 | - API Docs 12 | 13 | Building the documentation 14 | -------------------------- 15 | 16 | To build the documentation, you will need to have [Sphinx](http://sphinx-doc.org/) installed. 17 | 18 | In Terminal, `cd` to the `Docs` folder, and type: 19 | 20 | make html 21 | 22 | This will build the documentation in a subfolder named `_build`. 23 | 24 | Building the RoboFont extension 25 | ------------------------------- 26 | 27 | To build the RoboFont extension, run the script `build-extension.py` in RoboFont. 28 | 29 | Installing the extension 30 | ------------------------ 31 | 32 | Simply double-click the .roboFontExtension file to install in RoboFont. 33 | 34 | Also available via [Mechanic](http://www.robofontmechanic.com/). 35 | -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pyc 3 | .sass-cache -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/relations.html: -------------------------------------------------------------------------------- 1 | {%- if prev %} 2 |
3 |

{{ _('Previous') }}

4 |

5 | {{ prev.title }} 6 |

7 |
8 | {%- endif %} 9 | {%- if next %} 10 |
11 |

{{ _('Next') }}

12 |

13 | {{ next.title }} 14 |

15 |
16 | {%- endif %} 17 | -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/search.html: -------------------------------------------------------------------------------- 1 | {% extends "layout.html" %} 2 | {% set title = _('Search') %} 3 | {% set script_files = script_files + ['_static/searchtools.js'] %} 4 | {% block extrahead %} 5 | 8 | {{ super() }} 9 | {% endblock %} 10 | {% block body %} 11 |

{{ _('Search') }}

12 |
13 | 14 |

15 | {% trans %}Please activate JavaScript to enable the search 16 | functionality.{% endtrans %} 17 |

18 |
19 |

20 | {% trans %}From here you can search these documents. Enter your search 21 | words into the box below and click "search". Note that the search 22 | function will automatically search for all of the words. Pages 23 | containing fewer words won't appear in the result list.{% endtrans %} 24 |

25 | {% if search_performed %} 26 |

{{ _('Search Results') }}

27 | {% if not search_results %} 28 |

{{ _('Your search did not match any results.') }}

29 | {% endif %} 30 | {% endif %} 31 |
32 | {% if search_results %} 33 | 40 | {% endif %} 41 |
42 | {% endblock %} -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/searchbox.html: -------------------------------------------------------------------------------- 1 | 9 | 10 | -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/drawmodel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/drawmodel.jpg -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/drawmodel_header.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/drawmodel_header.jpg -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/logo.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_02.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_05.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_05.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_07.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_07.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_11.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_13.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_13.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_17.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_17.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_20.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_20.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_22.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_22.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_26.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_26.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_28.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_28.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_30.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_30.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/offdrawmodel_34.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/offdrawmodel_34.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_02.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_05.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_05.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_07.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_07.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_11.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_11.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_13.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_13.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_17.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_17.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_20.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_20.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_22.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_22.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_26.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_26.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_28.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_28.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_30.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_30.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/_img/ondrawmodel_34.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/_themes/roboFabTheme/static/_img/ondrawmodel_34.gif -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/static/sass2css.py: -------------------------------------------------------------------------------- 1 | # compile sass into css 2 | 3 | import os 4 | import subprocess 5 | 6 | # sass (CSS extension language) compiler 7 | # http://sass-lang.com/install 8 | 9 | def compileSass(sassPath): 10 | """Compile a sass file (and dependencies) into a single css file.""" 11 | cssPath = os.path.splitext(sassPath)[0] + ".css" 12 | subprocess.call(["sass", sassPath, cssPath]) 13 | 14 | baseFolder = os.path.dirname(__file__) 15 | 16 | for file_ in os.listdir(baseFolder): 17 | name, extension = os.path.splitext(file_) 18 | cssFile = "%s.%s" % (name, extension) 19 | cssPath = os.path.join(baseFolder, cssFile) 20 | if extension == ".sass": 21 | sassPath = os.path.join(baseFolder, file_) 22 | compileSass(sassPath) 23 | -------------------------------------------------------------------------------- /Docs/_themes/roboFabTheme/theme.conf: -------------------------------------------------------------------------------- 1 | [theme] 2 | inherit = basic 3 | stylesheet = robofab.css 4 | 5 | [options] 6 | rightsidebar = true 7 | stickysidebar = true 8 | collapsiblesidebar = true 9 | externalrefs = true 10 | 11 | bodyfont = "Lucida Grande", Monospace 12 | headerfont = Menlo, Monospace 13 | 14 | bgcolor = #FFFFFF 15 | textcolor = #3B3A3A 16 | linkcolor = #FF0000 17 | headercolor1 = #00FF00 18 | headercolor2 = #0000FF 19 | headerlinkcolor = #F2462C 20 | 21 | codebgcolor = #FFFFFF 22 | codetextcolor = #3B3A3A 23 | -------------------------------------------------------------------------------- /Docs/build-docs.py: -------------------------------------------------------------------------------- 1 | import os 2 | import shutil 3 | import subprocess 4 | 5 | baseFolder = os.path.dirname(__file__) 6 | sourceFolder = os.path.join(baseFolder, 'source') 7 | buildFolder = os.path.join(baseFolder, '_build') 8 | logFile = os.path.join(baseFolder, 'sphinx-log.txt') 9 | doctreesFolder = os.path.join(buildFolder, 'doctrees') 10 | htmlFolder = os.path.join(buildFolder, 'html') 11 | 12 | # delete build folder 13 | if os.path.exists(buildFolder): 14 | shutil.rmtree(buildFolder) 15 | 16 | # options 17 | # http://sphinx-doc.org/man/sphinx-build.html 18 | # or in Terminal: sphinx-build -h 19 | commands = [ 20 | '/usr/local/bin/sphinx-build', 21 | '-a', # build all files (not just new and changed) 22 | '-b', 'html', # builder: html / pdf / epub / text / etc. 23 | '-Q', # suppress console warnings and errors 24 | '-d', doctreesFolder, 25 | '-w', logFile, # write warnings and errors to file 26 | sourceFolder, 27 | htmlFolder 28 | ] 29 | 30 | # build docs 31 | p = subprocess.Popen(commands) 32 | stdout, stderr = p.communicate() 33 | 34 | # rewrite html for object map 35 | objectMapHtmlPath = os.path.join(os.path.join(htmlFolder, 'objects'), 'model.html') 36 | objectMapHtmlFile = open(objectMapHtmlPath, 'r') 37 | objectMapHtml = objectMapHtmlFile.read() 38 | 39 | findHtml = '' 40 | replaceHtml = '' 41 | 42 | objectMapHtml = objectMapHtml.replace(findHtml, replaceHtml) 43 | objectMapHtmlFile = open(objectMapHtmlPath, 'w') 44 | objectMapHtmlFile.write(objectMapHtml) 45 | -------------------------------------------------------------------------------- /Docs/docs.py: -------------------------------------------------------------------------------- 1 | # open a help window with RoboFab docs 2 | 3 | import os 4 | from mojo.UI import HelpWindow 5 | 6 | dirLib = os.path.dirname(__file__) 7 | dirBuild = os.path.join(dirLib, "_build") 8 | dirHtml = os.path.join(dirBuild, "html") 9 | htmlPath = os.path.join(dirHtml, "index.html") 10 | 11 | if os.path.exists(htmlPath): 12 | HelpWindow(htmlPath, 13 | title="RoboFab Docs", 14 | developer="RoboFab Developers", 15 | developerURL="http://robofab.org/" 16 | ) 17 | -------------------------------------------------------------------------------- /Docs/images/RAnchor.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/RAnchor.gif -------------------------------------------------------------------------------- /Docs/images/RComponent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/RComponent.gif -------------------------------------------------------------------------------- /Docs/images/RContour.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/RContour.gif -------------------------------------------------------------------------------- /Docs/images/RFont.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/RFont.gif -------------------------------------------------------------------------------- /Docs/images/RGlyph.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/RGlyph.gif -------------------------------------------------------------------------------- /Docs/images/RInfo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/RInfo.gif -------------------------------------------------------------------------------- /Docs/images/RKerning.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/RKerning.gif -------------------------------------------------------------------------------- /Docs/images/RPoint.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/RPoint.gif -------------------------------------------------------------------------------- /Docs/images/RSegment.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/RSegment.gif -------------------------------------------------------------------------------- /Docs/images/askstring_mac.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/askstring_mac.jpg -------------------------------------------------------------------------------- /Docs/images/askyesnocancel_mac.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/askyesnocancel_mac.jpg -------------------------------------------------------------------------------- /Docs/images/bPoint.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/bPoint.gif -------------------------------------------------------------------------------- /Docs/images/cent.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/cent.gif -------------------------------------------------------------------------------- /Docs/images/compatibility-scheme_2_01.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/compatibility-scheme_2_01.gif -------------------------------------------------------------------------------- /Docs/images/compatibility-scheme_2_02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/compatibility-scheme_2_02.gif -------------------------------------------------------------------------------- /Docs/images/compatibility-scheme_2_03.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/compatibility-scheme_2_03.gif -------------------------------------------------------------------------------- /Docs/images/compatibility-scheme_2_04.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/compatibility-scheme_2_04.gif -------------------------------------------------------------------------------- /Docs/images/compatibility-scheme_2_05.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/compatibility-scheme_2_05.gif -------------------------------------------------------------------------------- /Docs/images/compatibility-scheme_2_06.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/compatibility-scheme_2_06.gif -------------------------------------------------------------------------------- /Docs/images/compatibility-scheme_2_07.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/compatibility-scheme_2_07.gif -------------------------------------------------------------------------------- /Docs/images/compatibility-scheme_2_08.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/compatibility-scheme_2_08.gif -------------------------------------------------------------------------------- /Docs/images/condensor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/condensor.jpg -------------------------------------------------------------------------------- /Docs/images/contours.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/contours.jpg -------------------------------------------------------------------------------- /Docs/images/contours_bpoints.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/contours_bpoints.jpg -------------------------------------------------------------------------------- /Docs/images/contours_points.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/contours_points.jpg -------------------------------------------------------------------------------- /Docs/images/contours_segments.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/contours_segments.jpg -------------------------------------------------------------------------------- /Docs/images/contours_segments_points.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/contours_segments_points.jpg -------------------------------------------------------------------------------- /Docs/images/drawingexample.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/drawingexample.jpg -------------------------------------------------------------------------------- /Docs/images/drawmodel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/drawmodel.jpg -------------------------------------------------------------------------------- /Docs/images/exportmenu.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/exportmenu.gif -------------------------------------------------------------------------------- /Docs/images/findglyph_fl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/findglyph_fl.jpg -------------------------------------------------------------------------------- /Docs/images/flatten.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/flatten.gif -------------------------------------------------------------------------------- /Docs/images/fontLib.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/fontLib.gif -------------------------------------------------------------------------------- /Docs/images/glyphLib.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/glyphLib.gif -------------------------------------------------------------------------------- /Docs/images/glyphinterpol.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/glyphinterpol.gif -------------------------------------------------------------------------------- /Docs/images/glyphmath_examples_01.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/glyphmath_examples_01.gif -------------------------------------------------------------------------------- /Docs/images/glyphmath_examples_02.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/glyphmath_examples_02.gif -------------------------------------------------------------------------------- /Docs/images/glyphmath_examples_03.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/glyphmath_examples_03.gif -------------------------------------------------------------------------------- /Docs/images/glyphmath_examples_04.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/glyphmath_examples_04.gif -------------------------------------------------------------------------------- /Docs/images/glyphmath_examples_05.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/glyphmath_examples_05.gif -------------------------------------------------------------------------------- /Docs/images/halftone.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/halftone.gif -------------------------------------------------------------------------------- /Docs/images/logo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/logo.gif -------------------------------------------------------------------------------- /Docs/images/message_mac.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/message_mac.jpg -------------------------------------------------------------------------------- /Docs/images/rasteriser.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/rasteriser.gif -------------------------------------------------------------------------------- /Docs/images/selectfont_fl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/selectfont_fl.jpg -------------------------------------------------------------------------------- /Docs/images/selectglyph_fl.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/selectglyph_fl.jpg -------------------------------------------------------------------------------- /Docs/images/spike.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/spike.gif -------------------------------------------------------------------------------- /Docs/images/threshold.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/threshold.gif -------------------------------------------------------------------------------- /Docs/images/ufo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/Docs/images/ufo.jpg -------------------------------------------------------------------------------- /Docs/source/api/gString.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | gString 3 | ======= 4 | 5 | .. automodule:: robofab.gString 6 | :members: 7 | 8 | -------------------------------------------------------------------------------- /Docs/source/api/glifLib.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | glifLib 3 | ======= 4 | 5 | .. automodule:: robofab.glifLib 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/glifLib2.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | glifLib2 3 | ======== 4 | 5 | .. automodule:: robofab.glifLib2 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/index.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | API Docs 3 | ======== 4 | 5 | .. toctree:: 6 | :maxdepth: 1 7 | 8 | glifLib.rst 9 | glifLib2.rst 10 | gString.rst 11 | world.rst 12 | plistFromTree.rst 13 | plistlib.rst 14 | ufoLib.rst 15 | world.rst 16 | xmlTreeBuilder.rst 17 | tools/index.rst 18 | objects/index.rst 19 | pens/pens.rst -------------------------------------------------------------------------------- /Docs/source/api/interface/all/all.rst: -------------------------------------------------------------------------------- 1 | === 2 | all 3 | === 4 | 5 | .. automodule:: robofab.interface.all 6 | :members: 7 | 8 | .. toctree:: 9 | :maxdepth: 2 10 | 11 | dialogs.rst 12 | dialogs_default.rst 13 | dialogs_fontlab_legacy1.rst 14 | dialogs_fontlab_legacy2.rst 15 | dialogs_legacy.rst 16 | dialogs_mac_vanilla.rst 17 | -------------------------------------------------------------------------------- /Docs/source/api/interface/all/dialogs.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | dialogs 3 | ======= 4 | 5 | .. automodule:: robofab.interface.all.dialogs 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/interface/all/dialogs_default.rst: -------------------------------------------------------------------------------- 1 | =============== 2 | dialogs_default 3 | =============== 4 | 5 | .. automodule:: robofab.interface.all.dialogs_default 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/interface/all/dialogs_fontlab_legacy1.rst: -------------------------------------------------------------------------------- 1 | ======================= 2 | dialogs_fontlab_legacy1 3 | ======================= 4 | 5 | .. automodule:: robofab.interface.all.dialogs_fontlab_legacy1 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/interface/all/dialogs_fontlab_legacy2.rst: -------------------------------------------------------------------------------- 1 | ======================= 2 | dialogs_fontlab_legacy2 3 | ======================= 4 | 5 | .. automodule:: robofab.interface.all.dialogs_fontlab_legacy2 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/interface/all/dialogs_legacy.rst: -------------------------------------------------------------------------------- 1 | ============== 2 | dialogs_legacy 3 | ============== 4 | 5 | .. automodule:: robofab.interface.all.dialogs_legacy 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/interface/all/dialogs_mac_vanilla.rst: -------------------------------------------------------------------------------- 1 | =================== 2 | dialogs_mac_vanilla 3 | =================== 4 | 5 | .. automodule:: robofab.interface.all.dialogs_mac_vanilla 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/interface/interface.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | interface 3 | ========= 4 | 5 | .. automodule:: robofab.interface 6 | :members: 7 | 8 | .. toctree:: 9 | :maxdepth: 1 10 | 11 | all/all.rst 12 | mac/mac.rst 13 | win/win.rst 14 | -------------------------------------------------------------------------------- /Docs/source/api/interface/mac/mac.rst: -------------------------------------------------------------------------------- 1 | === 2 | mac 3 | === 4 | 5 | .. automodule:: robofab.interface.mac 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/interface/win/win.rst: -------------------------------------------------------------------------------- 1 | === 2 | win 3 | === 4 | 5 | .. automodule:: robofab.interface.win 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/misc/arrayTools.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | arrayTools 3 | ========== 4 | 5 | .. automodule:: robofab.misc.arrayTools 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/misc/bezierTools.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | bezierTools 3 | =========== 4 | 5 | .. automodule:: robofab.misc.bezierTools 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/misc/misc.rst: -------------------------------------------------------------------------------- 1 | ==== 2 | misc 3 | ==== 4 | 5 | .. py:module:: robofab.misc 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | 10 | arrayTools.rst 11 | bezierTools.rst 12 | speedTestCase.rst 13 | test.rst -------------------------------------------------------------------------------- /Docs/source/api/misc/speedTestCase.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | speedTestCase 3 | ============= 4 | 5 | .. automodule:: robofab.misc.speedTestCase 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/misc/test.rst: -------------------------------------------------------------------------------- 1 | ==== 2 | test 3 | ==== 4 | 5 | .. automodule:: robofab.misc.test 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/objects/index.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | objects 3 | ======= 4 | 5 | .. py:module:: robofab.objects 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | 10 | objectsBase.rst 11 | objectsFF.rst 12 | objectsFL.rst 13 | objectsRF.rst 14 | -------------------------------------------------------------------------------- /Docs/source/api/objects/objectsBase.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | objectsBase 3 | =========== 4 | 5 | .. automodule:: robofab.objects.objectsBase 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/objects/objectsFF.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | objectsFF 3 | ========= 4 | 5 | .. automodule:: robofab.objects.objectsFF 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/objects/objectsFL.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | objectsFL 3 | ========= 4 | 5 | .. automodule:: robofab.objects.objectsFL 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/objects/objectsRF.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | objectsRF 3 | ========= 4 | 5 | .. automodule:: robofab.objects.objectsRF 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/adapterPens.rst: -------------------------------------------------------------------------------- 1 | =========== 2 | adapterPens 3 | =========== 4 | 5 | .. automodule:: robofab.pens.adapterPens 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/angledMarginPen.rst: -------------------------------------------------------------------------------- 1 | =============== 2 | angledMarginPen 3 | =============== 4 | 5 | .. automodule:: robofab.pens.angledMarginPen 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/boundsPen.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | boundsPen 3 | ========= 4 | 5 | .. automodule:: robofab.pens.boundsPen 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/digestPen.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | digestPen 3 | ========= 4 | 5 | .. automodule:: robofab.pens.digestPen 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/filterPen.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | filterPen 3 | ========= 4 | 5 | .. automodule:: robofab.pens.filterPen 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/flPen.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | flPen 3 | ===== 4 | 5 | .. automodule:: robofab.pens.flPen 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/marginPen.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | marginPen 3 | ========= 4 | 5 | .. automodule:: robofab.pens.marginPen 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/mathPens.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | mathPens 3 | ======== 4 | 5 | .. automodule:: robofab.pens.mathPens 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/pens.rst: -------------------------------------------------------------------------------- 1 | ==== 2 | pens 3 | ==== 4 | 5 | .. py:module:: robofab.pens 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | 10 | adapterPens.rst 11 | angledMarginPen.rst 12 | boundsPen.rst 13 | digestPen.rst 14 | filterPen.rst 15 | flPen.rst 16 | marginPen.rst 17 | mathPens.rst 18 | pointPen.rst 19 | quartzPen.rst 20 | reverseContourPointPen.rst 21 | rfUFOPen.rst 22 | -------------------------------------------------------------------------------- /Docs/source/api/pens/pointPen.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | pointPen 3 | ======== 4 | 5 | .. automodule:: robofab.pens.pointPen 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/quartzPen.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | quartzPen 3 | ========= 4 | 5 | .. automodule:: robofab.pens.quartzPen 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/reverseContourPointPen.rst: -------------------------------------------------------------------------------- 1 | ====================== 2 | reverseContourPointPen 3 | ====================== 4 | 5 | .. automodule:: robofab.pens.reverseContourPointPen 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/pens/rfUFOPen.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | rfUFOPen 3 | ======== 4 | 5 | .. automodule:: robofab.pens.rfUFOPen 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/plistFromTree.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | plistFromTree 3 | ============= 4 | 5 | .. automodule:: robofab.plistFromTree 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/plistlib.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | plistlib 3 | ======== 4 | 5 | .. automodule:: robofab.plistlib 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/test/test.rst: -------------------------------------------------------------------------------- 1 | ==== 2 | test 3 | ==== 4 | 5 | .. py:module:: robofab.test 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | 10 | test_dialogs.rst 11 | test_fontLabUFOReadWrite.rst 12 | test_glifLib.rst 13 | test_noneLabUFOReadWrite.rst 14 | test_objectsFL.rst 15 | test_objectsUFO.rst 16 | test_pens.rst 17 | test_psHints.rst 18 | test_RInfoFL.rst 19 | test_RInfoRF.rst 20 | test_ufoLib.rst 21 | testSupport.rst 22 | -------------------------------------------------------------------------------- /Docs/source/api/test/test_dialogs.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | test_dialogs 3 | ============ 4 | 5 | .. automodule:: robofab.test.test_dialogs 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/test/test_glifLib.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | test_glifLib 3 | ============ 4 | 5 | .. automodule:: robofab.test.test_glifLib 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/test/test_noneLabUFOReadWrite.rst: -------------------------------------------------------------------------------- 1 | ======================== 2 | test_noneLabUFOReadWrite 3 | ======================== 4 | 5 | .. automodule:: robofab.test.test_noneLabUFOReadWrite 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/test/test_objectsUFO.rst: -------------------------------------------------------------------------------- 1 | =============== 2 | test_objectsUFO 3 | =============== 4 | 5 | .. automodule:: robofab.test.test_objectsUFO 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/test/test_pens.rst: -------------------------------------------------------------------------------- 1 | ========= 2 | test_pens 3 | ========= 4 | 5 | .. automodule:: robofab.test.test_pens 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/test/test_psHints.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | test_psHints 3 | ============ 4 | 5 | .. automodule:: robofab.test.test_psHints 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/accentBuilder.rst: -------------------------------------------------------------------------------- 1 | ============= 2 | accentBuilder 3 | ============= 4 | 5 | .. automodule:: robofab.tools.accentBuilder 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/fontlabFeatureSplitter.rst: -------------------------------------------------------------------------------- 1 | ====================== 2 | fontlabFeatureSplitter 3 | ====================== 4 | 5 | .. automodule:: robofab.tools.fontlabFeatureSplitter 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/glifExport.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | glifLib 3 | ======= 4 | 5 | .. automodule:: robofab.glifLib 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/glifImport.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | glifImport 3 | ========== 4 | 5 | .. automodule:: robofab.tools.glifImport 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/glyphConstruction.rst: -------------------------------------------------------------------------------- 1 | ================= 2 | glyphConstruction 3 | ================= 4 | 5 | .. automodule:: robofab.tools.glyphConstruction 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/glyphNameSchemes.rst: -------------------------------------------------------------------------------- 1 | ================ 2 | glyphNameSchemes 3 | ================ 4 | 5 | .. automodule:: robofab.tools.glyphNameSchemes 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/index.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | tools 3 | ===== 4 | 5 | .. automodule:: robofab.tools 6 | :members: 7 | 8 | .. toctree:: 9 | :maxdepth: 1 10 | 11 | accentBuilder.rst 12 | fontlabFeatureSplitter.rst 13 | glifExport.rst 14 | glifImport.rst 15 | glyphConstruction.rst 16 | glyphNameSchemes.rst 17 | objectDumper.rst 18 | otFeatures.rst 19 | proof.rst 20 | remote.rst 21 | rfPrefs.rst 22 | toolsAll.rst 23 | toolsFL.rst 24 | toolsRF.rst -------------------------------------------------------------------------------- /Docs/source/api/tools/objectDumper.rst: -------------------------------------------------------------------------------- 1 | ============ 2 | objectDumper 3 | ============ 4 | 5 | .. automodule:: robofab.tools.objectDumper 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/otFeatures.rst: -------------------------------------------------------------------------------- 1 | ========== 2 | otFeatures 3 | ========== 4 | 5 | .. automodule:: robofab.tools.otFeatures 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/proof.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | proof 3 | ===== 4 | 5 | .. automodule:: robofab.tools.proof 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/remote.rst: -------------------------------------------------------------------------------- 1 | ====== 2 | remote 3 | ====== 4 | 5 | .. automodule:: robofab.tools.remote 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/rfPrefs.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | rfPrefs 3 | ======= 4 | 5 | .. automodule:: robofab.tools.rfPrefs 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/toolsAll.rst: -------------------------------------------------------------------------------- 1 | ======== 2 | toolsAll 3 | ======== 4 | 5 | .. automodule:: robofab.tools.toolsAll 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/toolsFL.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | toolsFL 3 | ======= 4 | 5 | .. automodule:: robofab.tools.toolsFL 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/tools/toolsRF.rst: -------------------------------------------------------------------------------- 1 | ======= 2 | toolsRF 3 | ======= 4 | 5 | .. automodule:: robofab.tools.toolsRF 6 | :members: 7 | 8 | -------------------------------------------------------------------------------- /Docs/source/api/ufoLib.rst: -------------------------------------------------------------------------------- 1 | ====== 2 | ufoLib 3 | ====== 4 | 5 | .. automodule:: robofab.ufoLib 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/world.rst: -------------------------------------------------------------------------------- 1 | ===== 2 | world 3 | ===== 4 | 5 | .. automodule:: robofab.world 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/api/xmlTreeBuilder.rst: -------------------------------------------------------------------------------- 1 | ============== 2 | xmlTreeBuilder 3 | ============== 4 | 5 | .. automodule:: robofab.xmlTreeBuilder 6 | :members: 7 | -------------------------------------------------------------------------------- /Docs/source/howtos/index.rst: -------------------------------------------------------------------------------- 1 | How To's 2 | ======== 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | :hidden: 7 | 8 | ot_features.rst 9 | building_accents.rst 10 | fontlab_remote.rst 11 | generating_fonts.rst 12 | glifnames.rst 13 | lowlevel.rst 14 | interpolate.rst 15 | makeufo.rst 16 | scripting.rst 17 | world.rst 18 | understanding_contours.rst 19 | glyphmath.rst 20 | use_pens.rst 21 | use_lib.rst 22 | use_transformations.rst 23 | 24 | This section provides some cases on how to use the RoboFab objects in everyday type design work. 25 | 26 | - :doc:`OpenType Features in UFO `: How to import, export and work with features in UFO. 27 | - :doc:`Building accents `: Use RoboFab to build accented glyphs with components. 28 | - :doc:`FontLab Remote `: Use AppleEvents to control FontLab in Mac OSX 29 | - :doc:`Generate Fonts `: How to generate fonts with RoboFab in FontLab. 30 | - :doc:`Glyphnames versus GLIF-names `: How to use Robofab's glyph naming schemes for UFO export. 31 | - :doc:`How to get to FontLab stuff `: The naked methods and attributes. 32 | - :doc:`How to interpolate `: How to do interpolation with RoboFab objects. 33 | - :doc:`How to make a UFO `: Export and import UFO's in FontLab 34 | - :doc:`Scripting `: Simple examples. 35 | - :doc:`The world module `: What on earth is it for? 36 | - :doc:`Understanding Contours `: How contours, segments and points work. 37 | - :doc:`Using Glyph Math `: Applying math operators on glyph objects. 38 | - :doc:`Using Pens `: Playing with pen objects. 39 | - :doc:`Using the lib `: Make the ``glyph.lib`` and ``font.lib`` work for you. 40 | - :doc:`Using transformations `: Matrix transformations in RoboFab. 41 | -------------------------------------------------------------------------------- /Docs/source/howtos/lowlevel.rst: -------------------------------------------------------------------------------- 1 | How to get to FontLab's internals 2 | ================================= 3 | 4 | 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? 5 | 6 | Get Naked 7 | --------- 8 | 9 | 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: 10 | 11 | .. showcode:: ../../examples/howtos/lowLevel_00.py 12 | 13 | .. code:: 14 | 15 | < RFont font for TemplatefontPro Rg Regular > 16 | < Font 'TemplatefontPro Rg Regular' > 17 | -------------------------------------------------------------------------------- /Docs/source/intro/gettingstarted.rst: -------------------------------------------------------------------------------- 1 | Getting Started with RoboFab 2 | ============================ 3 | 4 | Installing 5 | ---------- 6 | 7 | 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 `. 8 | 9 | Some remarks for FontLab 4.6 users on Mac OSX 10 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 11 | 12 | - In MacOSX, you need to have admin permissions to install robofab in MacOS 9 Python. 13 | - 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. 14 | 15 | FontLab Macros 16 | -------------- 17 | 18 | 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. 19 | 20 | Then what? 21 | ^^^^^^^^^^ 22 | 23 | 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. 24 | -------------------------------------------------------------------------------- /Docs/source/intro/glossary.rst: -------------------------------------------------------------------------------- 1 | Glossary 2 | ======== 3 | 4 | .. glossary:: 5 | 6 | Glyphmath 7 | 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>`. 8 | 9 | NoneLab 10 | 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. 11 | -------------------------------------------------------------------------------- /Docs/source/intro/index.rst: -------------------------------------------------------------------------------- 1 | Introduction 2 | ============ 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | intro.rst 8 | summary.rst 9 | download.rst 10 | install.rst 11 | gettingstarted.rst 12 | history.rst 13 | limitations.rst 14 | links.rst 15 | tools.rst 16 | dialogs.rst 17 | ufo.rst 18 | glossary.rst 19 | -------------------------------------------------------------------------------- /Docs/source/intro/links.rst: -------------------------------------------------------------------------------- 1 | Links 2 | ===== 3 | 4 | Online resources 5 | ---------------- 6 | 7 | - `Join the RoboFab Google group `_ 8 | - `The FontLab Python page `_ 9 | - `Unofficial FontLab Python documentation `_ 10 | 11 | Tools 12 | ----- 13 | 14 | - `The FontTools home at sourceforge.net `_ 15 | - `The TTX page at LettError.com `_ 16 | - `MetricsMachine from TypeSupply `_: Industrial Strength Metrics for OS X. 17 | - `Lots of code from TypeSupply `_: Tools for developing tools and writing nice apps in Python. 18 | - `Superpolator.com `_: Infinite interpolation for RoboFab and FontLab. 19 | - `FontForge `_: A free font editor with Python and UFO support. 20 | - `The FontLab home page `_ 21 | 22 | Python 23 | ------ 24 | 25 | - `The main Python site Python.org `_ 26 | - `The Mac OSX section on Python.org `_ 27 | -------------------------------------------------------------------------------- /Docs/source/intro/summary.rst: -------------------------------------------------------------------------------- 1 | Executive Summary 2 | ================= 3 | 4 | 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. 5 | 6 | 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. 7 | 8 | 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. 9 | 10 | RoboFab offers a large selection of standardised UI dialogs, ranging from plain messaging to very powerful font and glyph retrieval functionality. 11 | 12 | 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. 13 | -------------------------------------------------------------------------------- /Docs/source/objects/RInfo.rst: -------------------------------------------------------------------------------- 1 | RInfo 2 | ===== 3 | 4 | .. image:: ../../images/RInfo.gif 5 | 6 | Usage 7 | ----- 8 | 9 | .. showcode:: ../../examples/objects/RInfo_00.py 10 | 11 | .. code:: 12 | 13 | MyFont Regular 14 | Huib van Krimpen 15 | Jan van Krimpen 16 | LTTR 17 | 1000 18 | 307 19 | #etc. 20 | 21 | Description 22 | ----------- 23 | 24 | ``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. 25 | 26 | Complete list of attributes 27 | --------------------------- 28 | 29 | 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`_. 30 | 31 | .. _UnifiedFontObject.org: http://unifiedFontObject.org/ 32 | .. _overview of the UFO2 font.info attributes: http://unifiedfontobject.org/versions/ufo2/fontinfo.html 33 | -------------------------------------------------------------------------------- /Docs/source/objects/index.rst: -------------------------------------------------------------------------------- 1 | Objects 2 | ======= 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | objects.rst 8 | model.rst 9 | RFont.rst 10 | RInfo.rst 11 | RGlyph.rst 12 | RContour.rst 13 | RPoint.rst 14 | bPoint.rst 15 | RSegment.rst 16 | RAnchor.rst 17 | RComponent.rst 18 | RKerning.rst 19 | pens.rst 20 | libs.rst 21 | psHints.rst 22 | psHintsGlyph.rst 23 | -------------------------------------------------------------------------------- /Docs/source/objects/libs.rst: -------------------------------------------------------------------------------- 1 | RLib 2 | ==== 3 | 4 | .. image:: ../../images/fontLib.gif 5 | 6 | Usage 7 | ----- 8 | 9 | .. showcode:: ../../examples/objects/RLib_00.py 10 | 11 | .. code:: 12 | 13 | < RLib for Salmiak-Regular > 14 | ['org.robofog.ufoExport.date', 15 | 'org.robofog.ufoExport.encoding.current', 16 | 'org.robofog.ufoExport.font.italicOffset', 17 | 'org.robofog.ufoExport.sourcePath'] 18 | 19 | Description 20 | ----------- 21 | 22 | ``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. 23 | 24 | Where is this data stored? 25 | ^^^^^^^^^^^^^^^^^^^^^^^^^^ 26 | 27 | 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. 28 | 29 | .. note:: 30 | 31 | 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>`. 32 | 33 | Methods 34 | ------- 35 | 36 | .. py:function:: keys() 37 | 38 | Return a list of the keys. Normal dictionary stuff. 39 | -------------------------------------------------------------------------------- /Docs/source/objects/model.rst: -------------------------------------------------------------------------------- 1 | RoboFab Object Model 2 | ==================== 3 | 4 | .. image:: ../../images/ObjectModel.svg 5 | 6 | `RFont `_ · `RInfo `_ · `RGlyph `_ · `RContour `_ · `RPoint `_ · `bPoint `_ · `RSegment `_ · `RAnchor `_ · `RComponent `_ · `RKerning `_ · `RLib `_ 7 | -------------------------------------------------------------------------------- /Docs/source/objects/psHintsGlyph.rst: -------------------------------------------------------------------------------- 1 | PostScript glyph hint values 2 | ============================ 3 | 4 | Usage 5 | ----- 6 | 7 | .. code:: 8 | 9 | # example of accessing the hint data. 10 | # from robofab.world import CurrentFont 11 | 12 | Description 13 | ----------- 14 | 15 | ``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. 16 | 17 | 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`_. 18 | 19 | .. _ChangeSet 44: http://code.robofab.com/changeset/44 20 | 21 | Attributes 22 | ^^^^^^^^^^ 23 | 24 | .. py:attribute:: hHints 25 | 26 | List of (position, width) tuples for horizontal. 27 | 28 | .. py:attribute:: vHints 29 | 30 | List of (position, width) tuples. 31 | 32 | Methods 33 | ^^^^^^^ 34 | 35 | .. py:function:: copy() 36 | 37 | Returns a copy of the object. Both in FontLab and NoneLab the copy will be an ``objectsRF.PostScriptFontHintValues``. 38 | 39 | .. py:function:: round() 40 | 41 | Round the values to ints as much as the nature of the values allows. 42 | 43 | .. note:: 44 | 45 | - ``blueScale`` is not rounded, it is a float. 46 | - ``forceBold`` is set to ``False`` if ``-0.5 < value < 0.5``. Otherwise it will be ``True``. 47 | - ``blueShift``, ``blueFuzz`` are rounded to integers. 48 | - ``stems`` are rounded to integers. 49 | - ``blues`` are rounded to integers. 50 | 51 | .. py:function:: asDict() 52 | 53 | Returns a dictionary with all attributes and values of this object. 54 | 55 | .. py:function:: fromDict(aDict) 56 | 57 | Rhis will look for familiar attributes in ``aDict`` and assign the value to the object. 58 | 59 | .. py:function:: update(anotherPSHintsObject) 60 | 61 | This will copy values from the other object. 62 | -------------------------------------------------------------------------------- /Docs/source/talks/dialogkit.rst: -------------------------------------------------------------------------------- 1 | DialogKit 2 | ========= 3 | 4 | DialogKit is a Python library for creating GUI dialogs in FontLab and Mac OS X Cocoa applications that have a Python layer. 5 | 6 | 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. 7 | 8 | `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. 9 | 10 | .. _Vanilla library: http://github.com/typesupply/vanilla 11 | .. _Download, documentation and examples on github: http://github.com/typesupply/dialogKit 12 | -------------------------------------------------------------------------------- /Docs/source/talks/index.rst: -------------------------------------------------------------------------------- 1 | Step-by-step 2 | ============ 3 | 4 | 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. 5 | 6 | .. toctree:: 7 | :maxdepth: 1 8 | :hidden: 9 | 10 | editors.rst 11 | python_basics.rst 12 | session1.rst 13 | session2.rst 14 | session3.rst 15 | interpolation.rst 16 | session6.rst 17 | session4.rst 18 | dialogkit.rst 19 | 20 | Sections 21 | -------- 22 | 23 | - :doc:`01: Editors `: Where to use RoboFab, where to edit. 24 | - :doc:`02: Basic Python `: Some rules, syntax. 25 | - :doc:`03: Font object, Info object `: Introduction to Font and Info objects, with examples. 26 | - :doc:`04: Glyph object and Pen object `: Introduction to Glyph and Pen objects. 27 | - :doc:`05: Kerning object and glyph building `: Introduction to the Kerning object, and a closer look at building glyphs from parts. 28 | - :doc:`06: Interpolation `: Scripting for interpolation. 29 | - :doc:`07: Production `: Scripting for production. 30 | - :doc:`08: NoneLab `: Adventures in NoneLab, scripting outside the box. 31 | - :doc:`09: Dialog Kit `: Interface toolkit for FontLab. 32 | 33 | Additional resources 34 | -------------------- 35 | 36 | The `Unified Font Object Specification site`_ featuring the UFO 2 extension. 37 | 38 | Find dozens of useful packages at the `TypeSupply.com public code repository`_, for instance DialogKit, Defcon, UFO2FDK and many more. 39 | 40 | .. _Unified Font Object Specification site : http://unifiedfontobject.org/ 41 | .. _TypeSupply.com public code repository : http://code.typesupply.com/ 42 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | RoboFab License Agreement 2 | 3 | Copyright (c) 2003-2013, The RoboFab Developers: 4 | Erik van Blokland 5 | Tal Leming 6 | Just van Rossum 7 | 8 | All rights reserved. 9 | 10 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 11 | 12 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 13 | 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. 14 | 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. 15 | 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. 16 | 17 | Up to date info on RoboFab: 18 | http://robofab.com/ 19 | 20 | This is the BSD license: 21 | http://www.opensource.org/licenses/BSD-3-Clause 22 | 23 | -------------------------------------------------------------------------------- /Lib/robofab/contrib/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Directory for contributed packages. 4 | Packages stored here can be imported from 5 | robofab.contrib. 6 | 7 | """ 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Lib/robofab/interface/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Directory for interface related modules. Stuff like widgets, 4 | dialog modules. Please keep them sorted by platform. 5 | 6 | interfaces/all : modules that are platform independent 7 | interfaces/mac : modules that are mac specific 8 | interfaces/win : modules that are windows specific 9 | 10 | """ 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Lib/robofab/interface/all/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Directory for interface related modules. Stuff like widgets, 4 | dialog modules. Please keep them sorted by platform. 5 | 6 | interfaces/all : modules that are platform independent 7 | interfaces/mac : modules that are mac specific 8 | interfaces/win : modules that are windows specific 9 | 10 | """ 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /Lib/robofab/interface/mac/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Directory for interface related modules. 4 | Stuff for MacOSX, widgets, quartz 5 | 6 | """ 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Lib/robofab/interface/win/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Directory for interface related modules. 4 | Stuff for Windows 5 | 6 | """ 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Lib/robofab/misc/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | arrayTools and bezierTools, originally from fontTools and using Numpy, 4 | now in a pure python implementation. This should ease the Numpy dependency 5 | for normal UFO input/output and basic scripting tasks. 6 | 7 | comparison test and speedtest provided. 8 | 9 | """ 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Lib/robofab/objects/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Directory for modules supporting 4 | 5 | Unified 6 | 7 | Font 8 | 9 | Objects 10 | 11 | """ 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Lib/robofab/path/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Directory for modules 4 | which do path stuff. 5 | Maybe it should move somewhere else. 6 | 7 | 8 | """ 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Lib/robofab/pens/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Directory for all pen modules. 4 | If you make a pen, put it here so that we can keep track of it. 5 | 6 | 7 | """ 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Lib/robofab/pens/quartzPen.py: -------------------------------------------------------------------------------- 1 | from fontTools.pens.basePen import BasePen 2 | 3 | class QuartzPen(BasePen): 4 | 5 | """Pen to draw onto a Quartz drawing context (Carbon.CG).""" 6 | 7 | def __init__(self, glyphSet, quartzContext): 8 | BasePen.__init__(self, glyphSet) 9 | self._context = quartzContext 10 | 11 | def _moveTo(self, (x, y)): 12 | self._context.CGContextMoveToPoint(x, y) 13 | 14 | def _lineTo(self, (x, y)): 15 | self._context.CGContextAddLineToPoint(x, y) 16 | 17 | def _curveToOne(self, (x1, y1), (x2, y2), (x3, y3)): 18 | self._context.CGContextAddCurveToPoint(x1, y1, x2, y2, x3, y3) 19 | 20 | def _closePath(self): 21 | self._context.closePath() 22 | -------------------------------------------------------------------------------- /Lib/robofab/plistFromTree.py: -------------------------------------------------------------------------------- 1 | """Small helper module to parse Plist-formatted data from trees as created 2 | by xmlTreeBuilder. 3 | """ 4 | 5 | 6 | __all__ = "readPlistFromTree" 7 | 8 | 9 | from plistlib import PlistParser 10 | 11 | 12 | def readPlistFromTree(tree): 13 | """Given a (sub)tree created by xmlTreeBuilder, interpret it 14 | as Plist-formatted data, and return the root object. 15 | """ 16 | parser = PlistTreeParser() 17 | return parser.parseTree(tree) 18 | 19 | 20 | class PlistTreeParser(PlistParser): 21 | 22 | def parseTree(self, tree): 23 | element, attributes, children = tree 24 | self.parseElement(element, attributes, children) 25 | return self.root 26 | 27 | def parseElement(self, element, attributes, children): 28 | self.handleBeginElement(element, attributes) 29 | for child in children: 30 | if isinstance(child, tuple): 31 | self.parseElement(child[0], child[1], child[2]) 32 | else: 33 | if not isinstance(child, unicode): 34 | # ugh, xmlTreeBuilder returns utf-8 :-( 35 | child = unicode(child, "utf-8") 36 | self.handleData(child) 37 | self.handleEndElement(element) 38 | 39 | 40 | if __name__ == "__main__": 41 | from xmlTreeBuilder import buildTree 42 | tree = buildTree("xxx.plist", stripData=0) 43 | print readPlistFromTree(tree) 44 | -------------------------------------------------------------------------------- /Lib/robofab/test/__init__.py: -------------------------------------------------------------------------------- 1 | """Directory for unit tests. 2 | 3 | Modules here are typically named text_.py, where is 4 | usually a module name, for example "test_flPen.py", but it can also be the name 5 | of an area or concept to be tested, for example "test_drawing.py". 6 | 7 | Testmodules should use the unittest framework. 8 | """ 9 | -------------------------------------------------------------------------------- /Lib/robofab/test/runAll.py: -------------------------------------------------------------------------------- 1 | import os 2 | import glob 3 | import unittest 4 | 5 | import robofab.test 6 | 7 | if __name__ == "__main__": 8 | testDir = os.path.dirname(robofab.test.__file__) 9 | testFiles = glob.glob1(testDir, "test_*.py") 10 | 11 | loader = unittest.TestLoader() 12 | suites = [] 13 | for fileName in testFiles: 14 | modName = "robofab.test." + fileName[:-3] 15 | print "importing", fileName 16 | try: 17 | mod = __import__(modName, {}, {}, ["*"]) 18 | except ImportError: 19 | print "*** skipped", fileName 20 | continue 21 | 22 | suites.append(loader.loadTestsFromModule(mod)) 23 | 24 | print "running tests..." 25 | testRunner = unittest.TextTestRunner(verbosity=0) 26 | testSuite = unittest.TestSuite(suites) 27 | testRunner.run(testSuite) 28 | -------------------------------------------------------------------------------- /Lib/robofab/test/test_objectsFL.py: -------------------------------------------------------------------------------- 1 | """This test suite for various FontLab-specific tests.""" 2 | 3 | 4 | import FL # needed to quickly raise ImportError if run outside of FL 5 | 6 | 7 | import os 8 | import tempfile 9 | import unittest 10 | 11 | from robofab.world import NewFont 12 | from robofab.test.testSupport import getDemoFontPath, getDemoFontGlyphSetPath 13 | from robofab.tools.glifImport import importAllGlifFiles 14 | from robofab.pens.digestPen import DigestPointPen 15 | from robofab.pens.adapterPens import SegmentToPointPen 16 | 17 | 18 | def getDigests(font): 19 | digests = {} 20 | for glyphName in font.keys(): 21 | pen = DigestPointPen() 22 | font[glyphName].drawPoints(pen) 23 | digests[glyphName] = pen.getDigest() 24 | return digests 25 | 26 | 27 | class FLTestCase(unittest.TestCase): 28 | 29 | def testUFOVersusGlifImport(self): 30 | font = NewFont() 31 | font.readUFO(getDemoFontPath(), doProgress=False) 32 | d1 = getDigests(font) 33 | font.close(False) 34 | font = NewFont() 35 | importAllGlifFiles(font.naked(), getDemoFontGlyphSetPath(), doProgress=False) 36 | d2 = getDigests(font) 37 | self.assertEqual(d1, d2) 38 | font.close(False) 39 | 40 | def testTwoUntitledFonts(self): 41 | font1 = NewFont() 42 | font2 = NewFont() 43 | font1.unitsPerEm = 1024 44 | font2.unitsPerEm = 2048 45 | self.assertNotEqual(font1.unitsPerEm, font2.unitsPerEm) 46 | font1.update() 47 | font2.update() 48 | font1.close(False) 49 | font2.close(False) 50 | 51 | 52 | if __name__ == "__main__": 53 | from robofab.test.testSupport import runTests 54 | runTests() 55 | -------------------------------------------------------------------------------- /Lib/robofab/tools/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Directory for all tool like code. 4 | Stuff that doesn't really belong to objects, pens, compilers etc. 5 | The code is split up into sections. 6 | 7 | 8 | """ 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Lib/robofab/tools/glyphNameSchemes.py: -------------------------------------------------------------------------------- 1 | """A separate module for glyphname to filename functions. 2 | 3 | glyphNameToShortFileName() generates a non-clashing filename for systems with 4 | filename-length limitations. 5 | """ 6 | 7 | MAXLEN = 31 8 | 9 | def glyphNameToShortFileName(glyphName, glyphSet): 10 | """Alternative glyphname to filename function. 11 | 12 | Features a garuanteed maximum filename for really long glyphnames, and clash testing. 13 | - all non-ascii characters are converted to "_" (underscore), including "." 14 | - all glyphnames which are too long are truncated and a hash is added at the end 15 | - the hash is generated from the whole glyphname 16 | - finally, the candidate glyphname is checked against the contents.plist 17 | and a incrementing number is added at the end if there is a clash. 18 | """ 19 | import binascii, struct, string 20 | ext = ".glif" 21 | ok = string.ascii_letters + string.digits + " _" 22 | h = binascii.hexlify(struct.pack(">l", binascii.crc32(glyphName))) 23 | n = '' 24 | for c in glyphName: 25 | if c in ok: 26 | if c != c.lower(): 27 | n += c + "_" 28 | else: 29 | n += c 30 | else: 31 | n += "_" 32 | if len(n + ext) < MAXLEN: 33 | return n + ext 34 | count = 0 35 | candidate = n[:MAXLEN - len(h + ext)] + h + ext 36 | if glyphSet is not None: 37 | names = glyphSet.getReverseContents() 38 | while candidate.lower() in names: 39 | candidate = n[:MAXLEN - len(h + ext + str(count))] + h + str(count) + ext 40 | count += 1 41 | return candidate 42 | -------------------------------------------------------------------------------- /Lib/robofab/tools/objectDumper.py: -------------------------------------------------------------------------------- 1 | """Simple and ugly way to print some attributes and properties of an object to stdout. 2 | FontLab doesn't have an object browser and sometimes we do need to look inside""" 3 | 4 | from pprint import pprint 5 | 6 | def classname(object, modname): 7 | """Get a class name and qualify it with a module name if necessary.""" 8 | name = object.__name__ 9 | if object.__module__ != modname: 10 | name = object.__module__ + '.' + name 11 | return name 12 | 13 | def _objectDumper(object, indent=0, private=False): 14 | """Collect a dict with the contents of the __dict__ as a quick means of peeking inside 15 | an instance. Some RoboFab locations do not support PyBrowser and still need debugging.""" 16 | data = {} 17 | data['__class__'] = "%s at %d"%(classname(object.__class__, object.__module__), id(object)) 18 | for k in object.__class__.__dict__.keys(): 19 | if private and k[0] == "_": 20 | continue 21 | x = object.__class__.__dict__[k] 22 | if hasattr(x, "fget"): #other means of recognising a property? 23 | try: 24 | try: 25 | value = _objectDumper(x.fget(self), 1) 26 | except: 27 | value = x.fget(self) 28 | data[k] = "[property, %s] %s"%(type(x.fget(self)).__name__, value) 29 | except: 30 | data[k] = "[property] (Error getting property value)" 31 | for k in object.__dict__.keys(): 32 | if private and k[0] == "_": 33 | continue 34 | try: 35 | data[k] = "[attribute, %s] %s"%(type(object.__dict__[k]).__name__, `object.__dict__[k]`) 36 | except: 37 | data[k] = "[attribute] (Error getting attribute value)" 38 | return data 39 | 40 | def flattenDict(dict, indent=0): 41 | t = [] 42 | k = dict.keys() 43 | k.sort() 44 | print 45 | print '---RoboFab Object Dump---' 46 | for key in k: 47 | value = dict[key] 48 | t.append(indent*"\t"+"%s: %s"%(key, value)) 49 | t.append('') 50 | return "\r".join(t) 51 | 52 | def dumpObject(object, private=False): 53 | print pprint(_objectDumper(object, private=private)) 54 | 55 | 56 | -------------------------------------------------------------------------------- /Lib/robofab/tools/toolsRF.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | Module for rf specific tool like code. 4 | 5 | """ 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | RoboFab 2 | ======= 3 | 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](http://unifiedfontobject.org). 4 | 5 | This library has been replaced with [fontParts](https://github.com/robofab-developers/fontParts). 6 | 7 | No further development is planned for RoboFab. 8 | 9 | ###Documentation 10 | 11 | Documentation for RoboFab lives at [RoboDocs](http://www.robodocs.info/roboFabDocs/source/index.html) 12 | 13 | Some how-to and older documentation can be found at [RoboFab.com](http://robofab.com) 14 | 15 | ###The Developers 16 | 17 | RoboFab is developed and maintained by Tal Leming, Erik van Blokland, Just van Rossum (in no particular order) 18 | 19 | ###Contact 20 | 21 | Email the RoboFab Consortium at 22 | i n f o (at) r o b o f a b (dot) o r g 23 | 24 | ###Copyrights 25 | 26 | This package is distributed under the BSD license. See the [license](LICENSE.txt). RoboFab is built in [Python](http://www.python.org). Parts of RoboFab use [fontTools](http://sourceforge.net/projects/fonttools/), an OpenSource font toolkit by Just van Rossum. Parts of the RoboFab library are built to work with code from [FontLab](http://www.fontlab.com), which is a product of Pyrus Inc. Parts of RoboFab implement the Property List file format in XML, copyright [Apple Computer](http://www.apple.com). Parts of RoboFab implement tables and names from PostScript and the OpenType FDK, copyright [Adobe](http://www.adobe.com). 27 | -------------------------------------------------------------------------------- /Scripts/Contributed/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | The code in the Contributions folder is covered, like the rest of RoboFab, 3 | by the BSD license, unless stated otherwise in the code itself. 4 | 5 | 6 | RoboFab License Agreement 7 | 8 | Copyright (c) 2005-2012, The RoboFab Developers: 9 | Erik van Blokland 10 | Tal Leming 11 | Just van Rossum 12 | 13 | All rights reserved. 14 | 15 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 16 | 17 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 18 | 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. 19 | 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. 20 | 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. 21 | 22 | Up to date info on RoboFab: 23 | http://robofab.com/ 24 | 25 | This is the BSD license: 26 | http://www.opensource.org/licenses/BSD-3-Clause 27 | 28 | -------------------------------------------------------------------------------- /Scripts/Contributed/ReadMe.txt: -------------------------------------------------------------------------------- 1 | RoboFab Contributed Scripts 2 | 3 | This is a folder with contributed scripts. -------------------------------------------------------------------------------- /Scripts/ReadMe.txt: -------------------------------------------------------------------------------- 1 | RoboFab Scripts 2 | 3 | These are some folders with scripts that can be run in FontLab. -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_AlignBPoints.py: -------------------------------------------------------------------------------- 1 | #FLM: Align Two Nodes 2 | 3 | """Align bPoints horizontally, vertically or both.""" 4 | 5 | from robofab.world import CurrentGlyph 6 | from robofab.interface.all.dialogs import TwoChecks 7 | 8 | glyph = CurrentGlyph() 9 | 10 | sel = [] 11 | 12 | #gather selected bPoints 13 | for contour in glyph.contours: 14 | if contour.selected: 15 | for bPoint in contour.bPoints: 16 | if bPoint.selected: 17 | sel.append(bPoint) 18 | 19 | if len(sel) != 0: 20 | xL = [] 21 | yL = [] 22 | 23 | #store up all coordinates for use later 24 | for bPoint in sel: 25 | x, y = bPoint.anchor 26 | xL.append(x) 27 | yL.append(y) 28 | 29 | if len(xL) > 1: 30 | w = TwoChecks("Horizontal", "Vertical", 0, 0) 31 | if w == None or w == 0: 32 | #the user doesn't want to align anything 33 | pass 34 | else: 35 | #find the center among all those bPoints 36 | minX = min(xL) 37 | maxX = max(xL) 38 | minY = min(yL) 39 | maxY = max(yL) 40 | cX = int(round((minX + maxX)/2)) 41 | cY = int(round((minY + maxY)/2)) 42 | 43 | #set the undo 44 | try: 45 | fl.SetUndo() 46 | except: 47 | pass 48 | 49 | #determine what the user wants to do 50 | noY = False 51 | noX = False 52 | if w == 1: 53 | #the user wants to align y 54 | noX = True 55 | elif w == 2: 56 | #the user wants to align x 57 | noY = True 58 | elif w == 3: 59 | #the user wants to align x and y 60 | pass 61 | 62 | 63 | for bPoint in sel: 64 | #get the move value for the bPoint 65 | aX, aY = bPoint.anchor 66 | mX = cX - aX 67 | mY = cY - aY 68 | if noY: 69 | #don't move the y 70 | mY = 0 71 | if noX: 72 | #don't move the x 73 | mX = 0 74 | bPoint.move((mX, mY)) 75 | glyph.update() 76 | -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_CorrectDirection.py: -------------------------------------------------------------------------------- 1 | """Correct contour direction for all glyphs in the font""" 2 | 3 | from robofab.world import OpenFont 4 | from robofab.interface.all.dialogs import ProgressBar 5 | 6 | font = OpenFont() 7 | bar = ProgressBar('Correcting contour direction...', len(font)) 8 | for glyph in font: 9 | bar.label(glyph.name) 10 | glyph.correctDirection() 11 | glyph.update() 12 | bar.tick() 13 | font.update() 14 | bar.close() -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_FindCompatibleGlyphs.py: -------------------------------------------------------------------------------- 1 | # 2 | # 3 | # make a list of which glyphs in this font could theoretically 4 | # interpolate with each other. 5 | # 6 | # 7 | 8 | 9 | from robofab.world import CurrentFont 10 | from robofab.pens.digestPen import DigestPointPen, DigestPointStructurePen 11 | 12 | compatibles = {} 13 | 14 | f = CurrentFont() 15 | for c in f: 16 | p = DigestPointStructurePen() 17 | c.drawPoints(p) 18 | d = p.getDigest() 19 | if not compatibles.has_key(d): 20 | compatibles[d] = [] 21 | compatibles[d].append(c.name) 22 | 23 | print 24 | print 'In %s, these glyphs could interpolate:'%(f.info.postscriptFullName) 25 | for d, names in compatibles.items(): 26 | if len(names) > 1: 27 | print ", ".join(names) -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_GlyphAppender.py: -------------------------------------------------------------------------------- 1 | #FLM: Glyph Appender 2 | 3 | """Add a glyph to the current glyph""" 4 | 5 | from robofab.world import CurrentFont, CurrentGlyph 6 | from robofab.interface.all.dialogs import SelectGlyph 7 | 8 | glyph = CurrentGlyph() 9 | font = CurrentFont() 10 | 11 | # select a glyph to add 12 | selected = SelectGlyph(font) 13 | # make sure that we are not trying add the current glyph to itself 14 | if selected.name != glyph.name: 15 | # preserve the current state 16 | try: 17 | fl.SetUndo() 18 | except: 19 | pass 20 | # add the selected glyph to the current glyph 21 | glyph.appendGlyph(selected) 22 | # always update the glyph! 23 | glyph.update() 24 | # and, just to be safe, update the font... 25 | font.update() 26 | -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_GlyphMath.py: -------------------------------------------------------------------------------- 1 | #FLM: Fun with GlyphMath 2 | 3 | # this example is meant to run with the RoboFab Demo Font 4 | # as the Current Font. So, if you're doing this in FontLab 5 | # import the Demo Font UFO first. 6 | 7 | from robofab.world import CurrentFont 8 | from random import random 9 | 10 | f = CurrentFont() 11 | condensedLight = f["a#condensed_light"] 12 | wideLight = f["a#wide_light"] 13 | wideBold = f["a#wide_bold"] 14 | 15 | diff = wideLight - condensedLight 16 | 17 | destination = f.newGlyph("a#deltaexperiment") 18 | destination.clear() 19 | x = wideBold + (condensedLight-wideLight)*random() 20 | 21 | destination.appendGlyph( x) 22 | destination.width = x.width 23 | destination.update() 24 | f.update() -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_InterpolPreview.py: -------------------------------------------------------------------------------- 1 | #FLM: Interpol Preview 2 | 3 | """This script draws all incremental interpolations 4 | between 1% and 99% of a selected glyph into a new font. 5 | It requires two open source fonts in FontLab.""" 6 | 7 | from robofab.interface.all.dialogs import SelectFont, OneList, ProgressBar 8 | from robofab.world import NewFont 9 | 10 | src1 = SelectFont('Select source font one:') 11 | if src1: 12 | src2 = SelectFont('Select source font two:') 13 | if src2: 14 | # collect a list of all compatible glyphs 15 | common = [] 16 | for glyphName in src1.keys(): 17 | if src2.has_key(glyphName): 18 | if src1[glyphName].isCompatible(src2[glyphName]): 19 | common.append(glyphName) 20 | common.sort() 21 | selName = OneList(common, 'Select a glyph:') 22 | if selName: 23 | dest = NewFont() 24 | g1 = src1[selName] 25 | g2 = src2[selName] 26 | count = 1 27 | bar = ProgressBar('Interpolating...', 100) 28 | # add the sourec one glyph for reference 29 | dest.newGlyph(selName + '_000') 30 | dest[selName + '_000'].width = src1[selName].width 31 | dest[selName + '_000'].appendGlyph(src1[selName]) 32 | dest[selName + '_000'].mark = 1 33 | dest[selName + '_000'].update() 34 | # add a new glyph and interpolate it 35 | while count != 100: 36 | factor = count * .01 37 | newName = selName + '_' + `count`.zfill(3) 38 | gD = dest.newGlyph(newName) 39 | gD.interpolate(factor, g1, g2) 40 | gD.update() 41 | bar.tick() 42 | count = count + 1 43 | # add the source two glyph for reference 44 | dest.newGlyph(selName + '_100') 45 | dest[selName + '_100'].width = src2[selName].width 46 | dest[selName + '_100'].appendGlyph(src2[selName]) 47 | dest[selName + '_100'].mark = 1 48 | dest[selName + '_100'].update() 49 | dest.update() 50 | bar.close() 51 | -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_InvertSelectedSegments.py: -------------------------------------------------------------------------------- 1 | #FLM: Invert Selection 2 | 3 | """Invert the selected segments in the current glyph""" 4 | 5 | from robofab.world import CurrentGlyph 6 | 7 | glyph = CurrentGlyph() 8 | for contour in glyph.contours: 9 | notSelected = [] 10 | for segment in contour.segments: 11 | if not segment.selected: 12 | notSelected.append(segment.index) 13 | contour.selected = False 14 | for index in notSelected: 15 | contour[index].selected = True 16 | glyph.update() -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_MakeCameoFont.py: -------------------------------------------------------------------------------- 1 | # FLM: Make Cameo Font 2 | 3 | """Make a cameo font. Pretty simple.""" 4 | 5 | from robofab.world import CurrentFont 6 | from robofab.interface.all.dialogs import Message 7 | 8 | buffer = 30 9 | scaleValue = .9 10 | 11 | f = CurrentFont() 12 | # clear all kerning 13 | f.kerning.clear() 14 | #determine top and bottom of the box 15 | t = f.info.unitsPerEm + f.info.descender + buffer 16 | b = f.info.descender - buffer 17 | #first decompose any components 18 | for g in f: 19 | g.decompose() 20 | #then proceed with the cameo operation 21 | for g in f: 22 | #catch negative sidebearings 23 | if g.leftMargin < 0: 24 | g.leftMargin = 0 25 | if g.rightMargin < 0: 26 | g.rightMargin = 0 27 | #scale the glyph and sidebearings 28 | leftMargin = int(round((g.rightMargin * scaleValue) + buffer)) 29 | rightMargin = int(round((g.rightMargin * scaleValue) + buffer)) 30 | g.scale((scaleValue, scaleValue), (int(round(g.width/2)), 0)) 31 | g.leftMargin = leftMargin 32 | g.rightMargin = rightMargin 33 | #determine the left and the right of the box 34 | l = 0 35 | r = g.width 36 | #draw the box using flPen 37 | p = g.getPen() 38 | p.moveTo((l, b)) 39 | p.lineTo((l, t)) 40 | p.lineTo((r, t)) 41 | p.lineTo((r, b)) 42 | p.closePath() 43 | #correct path direction 44 | g.correctDirection() 45 | #update the glyph 46 | g.update() 47 | #update the font 48 | f.update() 49 | #tell me when it is over 50 | Message('The highly complex "Cameo Operation" is now complete. Please examine the results and be thankful that RoboFab is on your side.') -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_PrintKerningCounts.py: -------------------------------------------------------------------------------- 1 | #FLM: Kerning Counter 2 | 3 | """print kerning counts for glyphs selected in the font window""" 4 | 5 | from robofab.world import CurrentFont 6 | 7 | font = CurrentFont() 8 | selectedGlyphs = font.selection 9 | kerning = font.kerning 10 | counts = kerning.occurrenceCount(selectedGlyphs) 11 | for glyphName in selectedGlyphs: 12 | print "%s: %s pairs"%(glyphName, counts[glyphName]) -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_PrintMeasuments.py: -------------------------------------------------------------------------------- 1 | #FLM: Print Measurments 2 | 3 | """print the distance and angle between two selected points""" 4 | 5 | from robofab.world import CurrentGlyph 6 | import math 7 | 8 | glyph = CurrentGlyph() 9 | 10 | selectedPoints = [] 11 | 12 | for contour in glyph.contours: 13 | if contour.selected: 14 | for segment in contour.segments: 15 | if segment.selected: 16 | onCurve = segment.onCurve 17 | point = (onCurve.x, onCurve.y) 18 | if point not in selectedPoints: 19 | selectedPoints.append(point) 20 | 21 | if len(selectedPoints) == 2: 22 | xList = [x for x, y in selectedPoints] 23 | yList = [y for x, y in selectedPoints] 24 | xList.sort() 25 | yList.sort() 26 | xDiff = xList[1] - xList[0] 27 | yDiff = yList[1] - yList[0] 28 | ang = round(math.atan2(yDiff, xDiff)*180/math.pi, 3) 29 | print "x:%s y:%s a:%s"%(xDiff, yDiff, ang) 30 | -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_RoundKerning.py: -------------------------------------------------------------------------------- 1 | """round all kerning values to increments of a specified value""" 2 | 3 | value = 100 4 | 5 | from robofab.world import CurrentFont 6 | 7 | font = CurrentFont() 8 | kerning = font.kerning 9 | startCount = len(kerning) 10 | kerning.round(value) 11 | font.update() 12 | print 'finished rounding kerning by %s.'%value 13 | print 'you started with %s kerning pairs.'%startCount 14 | print 'you now have %s kerning pairs.'%len(kerning) 15 | -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/demo_UFORemoveOverlap.py: -------------------------------------------------------------------------------- 1 | #FLM: UFO Remove Overlap 2 | 3 | """ 4 | Remove overlap on all glyphs in a .ufo font. 5 | 6 | This script sis more than a little silly, but it 7 | demonstrates how objectsRF and objectsFL can 8 | work hand in hand. 9 | """ 10 | 11 | from robofab.objects.objectsRF import OpenFont 12 | from robofab.objects.objectsFL import NewFont 13 | from robofab.interface.all.dialogs import ProgressBar 14 | 15 | ufoFont = OpenFont(note="Select a .ufo") 16 | if ufoFont: 17 | bar = ProgressBar('Removing Overlap...', len(ufoFont)) 18 | flFont = NewFont() 19 | flGlyph = flFont.newGlyph('OverlapRemover') 20 | for ufoGlyph in ufoFont: 21 | flPen = flGlyph.getPointPen() 22 | ufoGlyph.drawPoints(flPen) 23 | flGlyph.removeOverlap() 24 | ufoPen = ufoGlyph.getPointPen() 25 | ufoGlyph.clear() 26 | flGlyph.drawPoints(ufoPen) 27 | flGlyph.clear() 28 | bar.tick() 29 | flFont.close(save=0) 30 | bar.close() 31 | ufoFont.save(doProgress=True) 32 | -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/intro_008.py: -------------------------------------------------------------------------------- 1 | #FLM: 010 FontLab to RoboFab and Back 2 | 3 | # In which an adventurous glyph of your choice 4 | # makes a trip into RoboFab land, 5 | # and returns safely home after various inspections 6 | # and modifications. 7 | 8 | from robofab.world import CurrentGlyph, CurrentFont 9 | 10 | c = CurrentGlyph() 11 | f = CurrentFont() 12 | 13 | from robofab.objects.objectsRF import RGlyph 14 | d = RGlyph() 15 | 16 | # woa! d is now a rf version of a fl glyph! 17 | d.appendGlyph(c) 18 | d.width = 100 19 | 20 | c.printDump() 21 | d.printDump() 22 | 23 | e = f.newGlyph('copyTest') 24 | 25 | # dump the rf glyph back to a fl glyph! 26 | e.appendGlyph(d) 27 | 28 | # see, it still takes its own kind as well 29 | e.appendGlyph(f['a']) 30 | e.printDump() 31 | 32 | 33 | -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/intro_FontObject.py: -------------------------------------------------------------------------------- 1 | #FLM: RoboFab Intro, The Font Object 2 | 3 | # 4 | # 5 | # demo of the RoboFab font object 6 | # 7 | # 8 | 9 | import robofab 10 | 11 | # Let's talk to some of the font objects. 12 | # CurrentFont and CurrentGlyph are similar to 13 | # the RoboFog functions. They return a font 14 | # or Glyph object respectively. It will be the 15 | # front most font or the front most glyph. 16 | from robofab.world import CurrentFont, CurrentGlyph 17 | 18 | # This is a brief intro into Robofabs all singing and 19 | # dancing dialog class. It will produce simple 20 | # dialogs in almost any environment, FontLab, Python IDE, W. 21 | from robofab.interface.all.dialogs import Message 22 | 23 | # (make sure you have a font opened in FontLab) 24 | 25 | f = CurrentFont() 26 | # so now f is the name of a font object for the current font. 27 | 28 | if f == None: 29 | # let's see what dialog can do, a warning 30 | Message("You should open a font first, there's nothing to look at now!") 31 | else: 32 | # and another dialog. 33 | Message("The current font is %s"%(f.info.postscriptFullName)) 34 | 35 | # let's have a look at some of the attributes a RoboFab Font object has 36 | print "the number of glyphs:", len(f) 37 | 38 | # some of the attributes map straight to the FontLab Font class 39 | # We just straightened the camelCase here and there 40 | print "full name of this font:", f.info.postscriptFullName 41 | print "list of glyph names:", f.keys() 42 | print 'ascender:', f.info.ascender 43 | print 'descender:', f.info.descender 44 | -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/intro_GeneratingFonts.py: -------------------------------------------------------------------------------- 1 | #FLM: RoboFab Intro, Generating Fonts 2 | 3 | # 4 | # 5 | # demo generating fonts with robofab 6 | # 7 | # 8 | 9 | 10 | # Generating fonts with RoboFab is super easy! Let's have a look. 11 | # (you will need to have a font open in FontLab) 12 | 13 | from robofab.world import CurrentFont 14 | import os 15 | 16 | # A little function for making folders. we'll need it later. 17 | def makeFolder(path): 18 | #if the path doesn't exist, make it! 19 | if not os.path.exists(path): 20 | os.makedirs(path) 21 | 22 | # We need to have a font open for this demo to work 23 | font = CurrentFont() 24 | # This will tell us what folder the font is in 25 | fontPath = os.path.dirname(font.path) 26 | 27 | # We'll put the fonts into a folder called "FabFonts" next the .vfb file 28 | macPath = os.path.join(fontPath, 'FabFonts', 'ForMac') 29 | pcPath = os.path.join(fontPath, 'FabFonts', 'ForPC') 30 | bothPath = os.path.join(fontPath, 'FabFonts', 'ForBoth') 31 | 32 | # Now, we'll use that little function we made earlier to make the folders 33 | makeFolder(macPath) 34 | makeFolder(pcPath) 35 | makeFolder(bothPath) 36 | 37 | # A dict of all the font types we want to output 38 | fontTypes = { 'mac' : ['mactype1', 'macttf', 'macttdfont'], 39 | 'pc' : ['pctype1', 'pcmm'], 40 | 'both' : ['otfcff', 'otfttf'] 41 | } 42 | 43 | # Finally, let's generate the fonts! 44 | for macType in fontTypes['mac']: 45 | print "generating %s..."%macType 46 | font.generate(macType, macPath) 47 | for pcType in fontTypes['pc']: 48 | print "generating %s..."%pcType 49 | font.generate(pcType, pcPath) 50 | for bothType in fontTypes['both']: 51 | print "generating %s..."%bothType 52 | font.generate(bothType, bothPath) 53 | print 'Done!' 54 | 55 | # Wow! Could it be any easier than that? 56 | -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/intro_GlyphObject.py: -------------------------------------------------------------------------------- 1 | #FLM: RoboFab Intro, The Glyph Object 2 | 3 | # 4 | # 5 | # demo of the RoboFab glyph object 6 | # 7 | # 8 | 9 | import robofab 10 | from robofab.world import CurrentFont, CurrentGlyph 11 | from robofab.interface.all.dialogs import Message 12 | 13 | # (make sure you have a font opened in FontLab) 14 | 15 | 16 | 17 | # this code starts out the same as intro_FontObject 18 | f = CurrentFont() 19 | if f == None: 20 | Message("You should open a font first, there's nothing to look at now!") 21 | else: 22 | for g in f: 23 | print "glyphname:", g.name, ", glyph width:", g.width 24 | # so now g is a RoboFab Glyph object 25 | print "this glyph has %d contours" % len(g.contours) 26 | print "this glyph has %d components" % len(g.components) 27 | print "this glyph has %d anchors" % len(g.anchors) 28 | print 29 | 30 | # easy huh? 31 | # There are many more attributes and methods. 32 | # Most of these can be used to edit the font data. 33 | # Which makes them not suited for a simple intro as this 34 | # because we don't want to mess up your font. -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/intro_GlyphProperties.py: -------------------------------------------------------------------------------- 1 | #FLM: RoboFab Intro, Font and Glyph Lib 2 | 3 | # 4 | # 5 | # demo of glyph properties 6 | # 7 | # 8 | 9 | from robofab.world import OpenFont 10 | 11 | # This is a specific test of some features which are probably 12 | # still only supported in one glyph in the DemoFont.ufo, 13 | # which you can find the robofab/Data/ folder. Here is goes. 14 | 15 | f = OpenFont(None, "") 16 | 17 | for c in f: 18 | if not c.properties.isEmpty(): 19 | print c.properties.dump() 20 | 21 | # This prints the available GlyphProperties objects. 22 | # Not very impressive at the moment, but it means 23 | # that at least they're getting stored with the glyphs 24 | # and that they can be read and interpreted. 25 | -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/intro_InterpolateFonts.py: -------------------------------------------------------------------------------- 1 | #FLM: RoboFab Intro, Interpolating two fonts 2 | 3 | # Basic interpolation of two fonts. This is clean 4 | # non-FontLab specific implementation of 5 | # interpolating. This interpolation is strict: it 6 | # adds no points to contours, it does not alter 7 | # the outlines of the extremes in any possible 8 | # way. Note that this works in FontLab as well as 9 | # NoneLab. 10 | # 11 | # In fontlab: select two .vfb files, the result will be a new .vfb 12 | # In NoneLab: select two .ufo files, the result will be a new .ufo 13 | 14 | from robofab.world import OpenFont, RFont, RGlyph 15 | from robofab.pens.pointPen import AbstractPointPen 16 | from robofab.interface.all.dialogs import GetFolder 17 | 18 | f = OpenFont(None, "First master") 19 | g = OpenFont(None, "Second master") 20 | 21 | factor = .5 22 | 23 | d = RFont() 24 | d.interpolate(factor, f, g) 25 | 26 | path = GetFolder("Select a place to save this UFO") 27 | if path: 28 | d.save(path) 29 | 30 | print 'done' -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/intro_SimpleDrawing.py: -------------------------------------------------------------------------------- 1 | #FLM: RoboFab Intro, Simple Drawing 2 | 3 | # 4 | # 5 | # demo of drawing with RoboFab 6 | # 7 | # 8 | 9 | import robofab 10 | from robofab.world import CurrentFont, CurrentGlyph 11 | 12 | # (make sure you have a font opened in FontLab) 13 | 14 | 15 | 16 | f = CurrentFont() 17 | if f == None: 18 | Message("You should open a font first, there's nothing to look at now!") 19 | else: 20 | newGlyph = f.newGlyph('demoDrawGlyph', clear=True) 21 | newGlyph.width = 1000 22 | 23 | # The drawing is done through a specialised pen object. 24 | # There are pen objects for different purposes, this one 25 | # will draw in a FontLab glyph. The point of this is that 26 | # Robofab glyphs all respond to the standard set of 27 | # pen methods, and it is a simple way to re-interpret the 28 | # glyph data. 29 | 30 | # Make a new pen with the new glyph we just made 31 | pen = newGlyph.getPen() 32 | 33 | # Tell the pen to draw things 34 | pen.moveTo((100, 100)) 35 | pen.lineTo((800, 100)) 36 | pen.curveTo((1000, 300), (1000, 600), (800, 800)) 37 | pen.lineTo((100, 800)) 38 | pen.lineTo((100, 100)) 39 | 40 | # Done drawing: close the path 41 | pen.closePath() 42 | 43 | # Robofab objects still need to tell FontLab to update. 44 | newGlyph.update() 45 | f.update() 46 | 47 | # go check the font, it should now contain a new glyph named 48 | # "demoDrawGlyph" and it should look like a square. 49 | -------------------------------------------------------------------------------- /Scripts/RoboFabIntro/intro_StartHere.py: -------------------------------------------------------------------------------- 1 | #FLM: RoboFab Intro, Start here! 2 | 3 | # 4 | # 5 | # demo of starting up RoboFab 6 | # 7 | # 8 | 9 | import robofab 10 | 11 | # run this script (or 'macro' as FontLab calls them) 12 | # if it doesn't complain, you're good to go. 13 | # 14 | # If you get an "ImportError" it means that python 15 | # can't find the RoboFab module and that there is 16 | # probably something wrong with the way you 17 | # installed the package. 18 | 19 | from robofab.world import world 20 | print world 21 | 22 | # This should print something to the "Output" window. 23 | # It should tell you something about the environment 24 | # Robofab thinks it is in. 25 | -------------------------------------------------------------------------------- /Scripts/RoboFabUFO/ExportFontToUFO.py: -------------------------------------------------------------------------------- 1 | #FLM: Export Current Font to UFO Format 2 | 3 | """ 4 | Export the current font to UFO format. 5 | 6 | """ 7 | 8 | from robofab.world import CurrentFont 9 | from robofab.robofab.interface.all.dialogs import PutFile 10 | 11 | f = CurrentFont() 12 | if f.path is None: 13 | from robofab.interface.all.dialogs import PutFile 14 | path = PutFile("Please choose a name for the .ufo") 15 | if path is None: 16 | path = -1 # signal the code below the user has cancelled 17 | else: 18 | # writeUFO() will firgure out the destination .ufo path 19 | path = None 20 | if path != -1: 21 | f.writeUFO(path, doProgress=True) 22 | print 'DONE!' 23 | -------------------------------------------------------------------------------- /Scripts/RoboFabUFO/ExportOneGlyphToGlif.py: -------------------------------------------------------------------------------- 1 | #FLM: Glyph to Glif, not in UFO 2 | 3 | """ 4 | Dump the selected glyph to a Glif as a seperate, individual file. 5 | This is not saved through a GlyphSet and any contents.plist in the 6 | same directory will not be updated. If that's what you need use 7 | DumpOneGlyphToUFO.py 8 | 9 | """ 10 | 11 | 12 | from robofab.glifLib import writeGlyphToString 13 | from robofab.world import CurrentFont, CurrentGlyph 14 | from robofab.interface.all.dialogs import PutFile 15 | from robofab.tools.glyphNameSchemes import glyphNameToShortFileName 16 | import os 17 | 18 | f = CurrentFont() 19 | g = CurrentGlyph() 20 | 21 | if g is not None: 22 | todo = [g.name] 23 | else: 24 | todo = f.selection 25 | 26 | for c in todo: 27 | g = f[c] 28 | result = True 29 | data = writeGlyphToString(g.name, g, g.drawPoints) 30 | filename = glyphNameToShortFileName(g.name, None) 31 | file = PutFile("Save this glif as:") 32 | if file is not None: 33 | path = os.path.join(os.path.dirname(file), filename) 34 | print "saving to", path 35 | f = open(path, "w") 36 | f.write(data) 37 | f.close() 38 | 39 | 40 | print 'done' -------------------------------------------------------------------------------- /Scripts/RoboFabUFO/ExportOneGlyphToUFO.py: -------------------------------------------------------------------------------- 1 | #FLM: Export Selected or Current Glyph to UFO 2 | 3 | 4 | """ 5 | Dump the selected glyph to a .glif as part of a UFO. 6 | It saves the .glif through a GlyphSet and updates the contents.plist. 7 | 8 | Updated for UFO2 9 | """ 10 | 11 | 12 | from robofab.glifLib import GlyphSet 13 | from robofab.world import CurrentFont, CurrentGlyph 14 | from robofab.interface.all.dialogs import Message 15 | import os 16 | 17 | 18 | f = CurrentFont() 19 | g = CurrentGlyph() 20 | 21 | ufoPath = f.path.replace(".vfb", ".ufo") 22 | if not os.path.exists(ufoPath): 23 | Message("No UFO found for this font. I'm looking for \"%s\"."%(os.path.basename(ufoPath) )) 24 | 25 | if g is not None: 26 | todo = [g.name] 27 | else: 28 | todo = f.selection 29 | 30 | if todo: 31 | Message("Exporting %s to \"%s\"."%(", ".join(todo), os.path.basename(ufoPath) )) 32 | f.writeUFO(doHints=False, doInfo=False, doKerning=False, 33 | doGroups=False, doLib=False, doFeatures=False, glyphs=todo) 34 | 35 | else: 36 | Message("No glyphs selected for export.") 37 | 38 | print 'done' -------------------------------------------------------------------------------- /Scripts/RoboFabUFO/ExportSelectedGlyphsToUFO.py: -------------------------------------------------------------------------------- 1 | #FLM: Export Selected or Current Glyph to UFO 2 | 3 | 4 | """ 5 | Dump the selected glyph to a .glif as part of a UFO. 6 | It saves the .glif through a GlyphSet and updates the contents.plist. 7 | 8 | Updated for UFO2 9 | """ 10 | 11 | 12 | from robofab.glifLib import GlyphSet 13 | from robofab.world import CurrentFont, CurrentGlyph 14 | from robofab.interface.all.dialogs import Message 15 | import os 16 | 17 | 18 | f = CurrentFont() 19 | g = CurrentGlyph() 20 | todo = None 21 | 22 | ufoPath = f.path.replace(".vfb", ".ufo") 23 | if not os.path.exists(ufoPath): 24 | Message("No UFO found for this font. I'm looking for \"%s\"."%(os.path.basename(ufoPath) )) 25 | 26 | if g is not None: 27 | todo = [g.name] 28 | else: 29 | todo = f.selection 30 | 31 | if todo: 32 | Message("Exporting %s to \"%s\"."%(", ".join(todo), os.path.basename(ufoPath) )) 33 | f.writeUFO(doHints=False, doInfo=False, doKerning=False, 34 | doGroups=False, doLib=False, doFeatures=False, glyphs=todo) 35 | 36 | else: 37 | Message("No glyphs selected for export.") 38 | 39 | print 'done' -------------------------------------------------------------------------------- /Scripts/RoboFabUFO/ExportSelectedGlyphsToUFOForAllFonts.py: -------------------------------------------------------------------------------- 1 | #FLM: Selected glyphs from all fonts to UFO 2 | 3 | 4 | """ 5 | Get the name of the current glyph, 6 | then for each open font, export that glyph to UFO. 7 | It saves the .glif through a GlyphSet and updates the contents.plist. 8 | 9 | This script is useful when you're working on several interpolation 10 | masters as separate vfb source files. 11 | 12 | EvB 08 13 | """ 14 | 15 | 16 | from robofab.glifLib import GlyphSet 17 | from robofab.world import CurrentFont, CurrentGlyph, AllFonts 18 | from robofab.interface.all.dialogs import Message, GetFileOrFolder 19 | from robofab.tools.glyphNameSchemes import glyphNameToShortFileName 20 | import os 21 | 22 | f = CurrentFont() 23 | g = CurrentGlyph() 24 | 25 | f.save() 26 | 27 | todo = f.selection 28 | print "selection", todo 29 | if g is not None: 30 | todo.append(g.name) 31 | 32 | for f in AllFonts(): 33 | ufoPath = None 34 | print "f.path", f, f.path 35 | if f.path is None: 36 | # huh, in case there is a ghost font. 37 | print "skipping", f 38 | continue 39 | ufoPath = f.path.replace(".vfb", ".ufo") 40 | if not os.path.exists(ufoPath): 41 | ufoPath = GetFileOrFolder("Select a UFO to save the GLIF in:") 42 | if ufoPath.find(".ufo") == -1: 43 | Message("You need to select an UFO. Quitting.") 44 | ufoPath = None 45 | if ufoPath is None: 46 | continue 47 | for c in todo: 48 | if c not in f: 49 | print "font is missing", c 50 | continue 51 | g = f[c] 52 | path = os.path.join(os.path.dirname(ufoPath), os.path.basename(ufoPath), "glyphs") 53 | print "saving glyph %s in %s"%(g.name, path) 54 | gs = GlyphSet(path, glyphNameToFileNameFunc=glyphNameToShortFileName) 55 | gs.writeGlyph(g.name, g, g.drawPoints) 56 | gs.writeContents() 57 | 58 | print 'done' -------------------------------------------------------------------------------- /Scripts/RoboFabUFO/ImportFontFromUFO.py: -------------------------------------------------------------------------------- 1 | #FLM: Import .ufo File into FontLab 2 | 3 | from robofab.world import NewFont 4 | from robofab.interface.all.dialogs import GetFileOrFolder 5 | 6 | path = GetFileOrFolder("Please select a .ufo") 7 | if path is not None: 8 | font = NewFont() 9 | font.readUFO(path, doProgress=True) 10 | font.update() 11 | print 'DONE!' 12 | -------------------------------------------------------------------------------- /Scripts/RoboFabUFO/ImportOneGlyphFromUFO.py: -------------------------------------------------------------------------------- 1 | #FLM: Single Glyph from a UFO 2 | 3 | """Import one glyph from a .ufo, 4 | i.e. a single .glif file. 5 | """ 6 | 7 | from robofab.world import CurrentFont 8 | from robofab.objects.objectsRF import OpenFont 9 | from robofab.interface.all.dialogs import SelectGlyph, Message 10 | 11 | flFont = CurrentFont() 12 | if flFont is None: 13 | Message("Please have a FontLab destination font ready..") 14 | else: 15 | # pick a .ufo 16 | rfFont = OpenFont() 17 | if rfFont is not None: 18 | # pick a glyph in the .ufo 19 | rfGlyph = SelectGlyph(rfFont) 20 | if rfGlyph is not None: 21 | # make a new glyph in the FL font 22 | flGlyph = flFont.newGlyph(rfGlyph.name, clear=True) 23 | # draw the glyph into the FL font 24 | pen = flGlyph.getPointPen() 25 | rfGlyph.drawPoints(pen) 26 | # set the width, unicodes and lib 27 | flGlyph.width = rfGlyph.width 28 | flGlyph.unicodes = rfGlyph.unicodes 29 | flGlyph.lib = rfGlyph.lib 30 | flGlyph.note = rfGlyph.note 31 | flGlyph.update() 32 | flFont.update() 33 | -------------------------------------------------------------------------------- /Scripts/RoboFabUFO/ImportUFOBatch.py: -------------------------------------------------------------------------------- 1 | #FLM: Import all UFOs in a folder 2 | 3 | """ 4 | 5 | Import all UFOs in a folder 6 | 7 | Note this is a relatively dumb import script. 8 | 9 | """ 10 | from robofab.world import NewFont 11 | 12 | from robofab.interface.all.dialogs import GetFolder 13 | import os 14 | 15 | 16 | def globUFO(dir, filter=None): 17 | """Collect paths for all ufos in dir. 18 | Check for nested dirs. 19 | Optionally, select only ufos which match a filter string. 20 | """ 21 | ufo = [] 22 | names = os.listdir(dir) 23 | for n in names: 24 | p = os.path.join(dir, n) 25 | if n[-4:] == ".ufo": 26 | if filter is not None: 27 | if dir.find(filter) <> -1: 28 | ufo.append(p) 29 | else: 30 | ufo.append(p) 31 | continue 32 | if os.path.isdir(p): 33 | ufo += globUFO(p, filter) 34 | return ufo 35 | 36 | dir = GetFolder() 37 | ufo = globUFO(dir) 38 | 39 | for path in ufo: 40 | font = NewFont() 41 | font.readUFO(path, doProgress=True) 42 | font.update() 43 | vfbPath = path[:-4] + ".vfb" 44 | font.save(vfbPath) 45 | print 'DONE!' 46 | -------------------------------------------------------------------------------- /Scripts/RoboFabUFO/SelectedGlyphsToUFO.py: -------------------------------------------------------------------------------- 1 | #FLM: Export selected glyphs to UFO 2 | 3 | 4 | """ 5 | Dump the selected glyph to a .glif as part of a UFO. 6 | It saves the .glif through a GlyphSet and updates the contents.plist. 7 | 8 | EvB 08 9 | """ 10 | 11 | 12 | from robofab.glifLib import GlyphSet 13 | from robofab.world import CurrentFont, CurrentGlyph 14 | from robofab.interface.all.dialogs import Message, GetFileOrFolder 15 | from robofab.tools.glyphNameSchemes import glyphNameToShortFileName 16 | import os 17 | 18 | f = CurrentFont() 19 | g = CurrentGlyph() 20 | 21 | f.save() 22 | 23 | ufoPath = None 24 | ufoPath = f.path.replace(".vfb", ".ufo") 25 | if not os.path.exists(ufoPath): 26 | ufoPath = GetFileOrFolder("Select a UFO to save the GLIF in:") 27 | if ufoPath.find(".ufo") == -1: 28 | Message("You need to select an UFO. Quitting.") 29 | ufoPath = None 30 | 31 | if ufoPath is not None: 32 | todo = f.selection 33 | print "selection", todo 34 | if g is not None: 35 | todo.append(g.name) 36 | for c in todo: 37 | g = f[c] 38 | path = os.path.join(os.path.dirname(ufoPath), os.path.basename(ufoPath), "glyphs") 39 | print "saving glyph %s in %s"%(g.name, path) 40 | gs = GlyphSet(path, glyphNameToFileNameFunc=glyphNameToShortFileName) 41 | gs.writeGlyph(g.name, g, g.drawPoints) 42 | gs.writeContents() 43 | 44 | print 'done' -------------------------------------------------------------------------------- /Scripts/RoboFabUFO/SelectedGlyphsToUFOForAllFonts.py: -------------------------------------------------------------------------------- 1 | #FLM: Selected glyphs from all fonts to UFO 2 | 3 | 4 | """ 5 | Get the name of the current glyph, 6 | then for each open font, export that glyph to UFO. 7 | It saves the .glif through a GlyphSet and updates the contents.plist. 8 | 9 | This script is useful when you're working on several interpolation 10 | masters as separate vfb source files. 11 | 12 | EvB 08 13 | """ 14 | 15 | 16 | from robofab.glifLib import GlyphSet 17 | from robofab.world import CurrentFont, CurrentGlyph, AllFonts 18 | from robofab.interface.all.dialogs import Message, GetFileOrFolder 19 | from robofab.tools.glyphNameSchemes import glyphNameToShortFileName 20 | import os 21 | 22 | f = CurrentFont() 23 | g = CurrentGlyph() 24 | 25 | f.save() 26 | 27 | todo = f.selection 28 | print "selection", todo 29 | if g is not None: 30 | todo.append(g.name) 31 | 32 | for f in AllFonts(): 33 | ufoPath = None 34 | print "f.path", f, f.path 35 | if f.path is None: 36 | # huh, in case there is a ghost font. 37 | print "skipping", f 38 | continue 39 | ufoPath = f.path.replace(".vfb", ".ufo") 40 | if not os.path.exists(ufoPath): 41 | ufoPath = GetFileOrFolder("Select a UFO to save the GLIF in:") 42 | if ufoPath.find(".ufo") == -1: 43 | Message("You need to select an UFO. Quitting.") 44 | ufoPath = None 45 | if ufoPath is None: 46 | continue 47 | for c in todo: 48 | if c not in f: 49 | print "font is missing", c 50 | continue 51 | g = f[c] 52 | path = os.path.join(os.path.dirname(ufoPath), os.path.basename(ufoPath), "glyphs") 53 | print "saving glyph %s in %s"%(g.name, path) 54 | gs = GlyphSet(path, glyphNameToFileNameFunc=glyphNameToShortFileName) 55 | gs.writeGlyph(g.name, g, g.drawPoints) 56 | gs.writeContents() 57 | 58 | print 'done' -------------------------------------------------------------------------------- /Scripts/RoboFabUtils/FontToUfo.py: -------------------------------------------------------------------------------- 1 | """Use fonttools to open TrueType, Type 1 or OpenType, then write a UFO.""" 2 | 3 | from robofab.tools.toolsAll import fontToUFO, guessFileType 4 | 5 | if len(sys.argv) not in (2, 3): 6 | print "usage: FontToUfo.py []" 7 | sys.exit(1) 8 | src = sys.argv[1] 9 | if len(sys.argv) == 3: 10 | dst = sys.argv[2] 11 | else: 12 | base, ext = os.path.splitext(src) 13 | dst = base + ".ufo" 14 | 15 | fileType = guessFileType(src) 16 | if fileType is None: 17 | print "Can't determine input file type" 18 | sys.exit(1) 19 | print "Converting %s %r to %r" % (fileType, src, dst) 20 | fontToUFO(src, dst) 21 | -------------------------------------------------------------------------------- /Scripts/RoboFabUtils/GenerateKernProof.py: -------------------------------------------------------------------------------- 1 | #FLM: Make Kerning Proof of selection 2 | 3 | """Generate an InDesign 2.0 tagged text file 4 | for every possible glyph combination in the current font.""" 5 | 6 | from robofab.tools.proof import IDTaggedText 7 | from robofab.world import CurrentFont 8 | 9 | f = CurrentFont() 10 | 11 | fontSize = 36 12 | 13 | id = IDTaggedText(f.info.familyName, f.info.styleName, size=fontSize) 14 | 15 | names = f.selection 16 | names.sort() 17 | 18 | for l in names: 19 | left = f[l] 20 | for r in names: 21 | right = f[r] 22 | id.addGlyph(left.index) 23 | id.addGlyph(right.index) 24 | id.add(' ') 25 | print 'finished all pairs starting with', left.name 26 | 27 | from robofab.interface.all.dialogs import PutFile 28 | path = PutFile("Save the tagged file:", "KerningProofTags.txt") 29 | if path: 30 | id.save(path) 31 | 32 | -------------------------------------------------------------------------------- /Scripts/RoboFabUtils/RewriteDemoFont.py: -------------------------------------------------------------------------------- 1 | """Read all glyphs from the demo font, and write them out again. 2 | This is useful for testing round-tripping stability, but also to 3 | update the font when the GLIF format changes. The third application 4 | is to update the contents.plist file in case glyphs have been added 5 | or removed. 6 | """ 7 | 8 | 9 | import os 10 | from robofab.test.testSupport import getDemoFontPath 11 | from robofab.glifLib import GlyphSet 12 | from robofab.pens.adapterPens import GuessSmoothPointPen 13 | 14 | ufoPath = getDemoFontPath() 15 | glyphSet = GlyphSet(os.path.join(ufoPath, "glyphs")) 16 | glyphSet.rebuildContents() # ignore existing contents.plist, rebuild from dir listing 17 | for name in glyphSet.keys(): 18 | g = glyphSet[name] 19 | g.drawPoints(None) # force all attrs to be loaded 20 | def drawPoints(pen): 21 | pen = GuessSmoothPointPen(pen) 22 | g.drawPoints(pen) 23 | glyphSet.writeGlyph(name, g, drawPoints) 24 | 25 | glyphSet.writeContents() # write out contents.plist 26 | 27 | -------------------------------------------------------------------------------- /Scripts/RoboFabUtils/RobustBatchGenerate.py: -------------------------------------------------------------------------------- 1 | # a more robust batch generator that only has one font open at the time. 2 | 3 | from robofab.interface.all.dialogs import GetFolder 4 | from robofab.world import RFont, OpenFont 5 | import os 6 | 7 | def collectSources(root): 8 | files = [] 9 | ext = ['.vfb'] 10 | names = os.listdir(root) 11 | for n in names: 12 | if os.path.splitext(n)[1] in ext: 13 | files.append(os.path.join(root, n)) 14 | return files 15 | 16 | # A little function for making folders. we'll need it later. 17 | def makeFolder(path): 18 | #if the path doesn't exist, make it! 19 | if not os.path.exists(path): 20 | os.makedirs(path) 21 | 22 | def makeDestination(root): 23 | macPath = os.path.join(root, 'FabFonts', 'ForMac') 24 | makeFolder(macPath) 25 | return macPath 26 | 27 | def generateOne(f, dstDir): 28 | print "generating %s"%f.info.postscriptFullName 29 | f.generate('mactype1', dstDir) 30 | 31 | 32 | f = GetFolder() 33 | 34 | if f is not None: 35 | paths = collectSources(f) 36 | dstDir = makeDestination(f) 37 | 38 | for f in paths: 39 | font = None 40 | try: 41 | font = OpenFont(f) 42 | generateOne(font, dstDir) 43 | 44 | finally: 45 | if font is not None: 46 | font.close(False) 47 | 48 | 49 | print 'done' -------------------------------------------------------------------------------- /Scripts/RoboFabUtils/Start_FL_Remote.py: -------------------------------------------------------------------------------- 1 | #FLM: Start FontLab remote 2 | 3 | # On MacOS this will make FontLab accept apple events. 4 | # It will assume the event contains a piece of executable 5 | # python code and run it. The results of the python code 6 | # are then returned in the reply. 7 | # 8 | # Check the code in robofab/tools/remote.py for more 9 | # functionality. For instance, it contains several 10 | # functions to send and receive glyphs from outside 11 | # FontLab, offering a way to make your NoneLab Python 12 | # scripts communicate with FontLab. 13 | 14 | from robofab.tools.remote import * 15 | 16 | -------------------------------------------------------------------------------- /Scripts/RoboFabUtils/TestFontEquality.py: -------------------------------------------------------------------------------- 1 | from robofab.world import AllFonts 2 | 3 | print "Compare all fonts in the AllFonts list with each other:" 4 | 5 | 6 | af = AllFonts() 7 | 8 | results = [] 9 | line = [] 10 | for n in af: 11 | line.append(`n.info.postscriptFullName`) 12 | results.append(line) 13 | 14 | for i in range(len(af)): 15 | one = af[i] 16 | line = [] 17 | line.append(af[i].info.postscriptFullName) 18 | for j in range(len(af)): 19 | other = af[j] 20 | line.append(`one==other`) 21 | if one == other: 22 | print "same: ", one.path, other.path 23 | results.append(line) 24 | 25 | for n in results: 26 | print n 27 | 28 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO1).ufo/glyphs/A_.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO1).ufo/glyphs/B_.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO1).ufo/glyphs/contents.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | A 6 | A_.glif 7 | B 8 | B_.glif 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO1).ufo/groups.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | group1 6 | 7 | A 8 | 9 | group2 10 | 11 | A 12 | B 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO1).ufo/kerning.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | A 6 | 7 | B 8 | 100 9 | 10 | B 11 | 12 | A 13 | -200 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO1).ufo/lib.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | org.robofab.opentype.classes 6 | @myClass = [A B]; 7 | 8 | org.robofab.opentype.featureorder 9 | 10 | liga 11 | 12 | org.robofab.opentype.features 13 | 14 | liga 15 | feature liga { 16 | sub A A by b; 17 | } liga; 18 | 19 | 20 | org.robofab.postScriptHintData 21 | 22 | blueFuzz 23 | 1 24 | blueScale 25 | 0.039625 26 | blueShift 27 | 7 28 | blueValues 29 | 30 | 31 | 500 32 | 510 33 | 34 | 35 | familyBlues 36 | 37 | 38 | 500 39 | 510 40 | 41 | 42 | familyOtherBlues 43 | 44 | 45 | -260 46 | -250 47 | 48 | 49 | forceBold 50 | 51 | hStems 52 | 53 | 100 54 | 120 55 | 56 | otherBlues 57 | 58 | 59 | -260 60 | -250 61 | 62 | 63 | vStems 64 | 65 | 80 66 | 90 67 | 68 | 69 | org.robofab.testFontLibData 70 | Foo Bar 71 | 72 | 73 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO1).ufo/metainfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | creator 6 | org.robofab.ufoLib 7 | formatVersion 8 | 1 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO2).ufo/features.fea: -------------------------------------------------------------------------------- 1 | @myClass = [A B]; 2 | 3 | feature liga { 4 | sub A A by b; 5 | } liga; 6 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO2).ufo/glyphs/A_.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO2).ufo/glyphs/B_.glif: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO2).ufo/glyphs/contents.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | A 6 | A_.glif 7 | B 8 | B_.glif 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO2).ufo/groups.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | group1 6 | 7 | A 8 | 9 | group2 10 | 11 | A 12 | B 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO2).ufo/kerning.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | A 6 | 7 | B 8 | 100 9 | 10 | B 11 | 12 | A 13 | -200 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO2).ufo/lib.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | org.robofab.testFontLibData 6 | Foo Bar 7 | 8 | 9 | -------------------------------------------------------------------------------- /TestData/TestFont1 (UFO2).ufo/metainfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | creator 6 | org.robofab.ufoLib 7 | formatVersion 8 | 2 9 | 10 | 11 | -------------------------------------------------------------------------------- /TestData/TestFont1.vfb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/robotools/robofab/2ea0b6201cf67be866f6b6afa9574ef7219fd140/TestData/TestFont1.vfb -------------------------------------------------------------------------------- /Tools/autoDistroBuilder.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | if len(sys.argv) == 2: 4 | # we're called as a shellscript 5 | # assume the path is the second argument 6 | testBuildFolder = sys.argv[1] 7 | else: 8 | testBuildFolder = "/Users/erik/Develop/svn.robofab.com/randomOtherDifferentDirectory" 9 | 10 | 11 | """ 12 | 13 | Build a robofab distro from SVN 14 | Store it in a new directory not in the robofab tree 15 | Write an html page. 16 | 17 | """ 18 | 19 | from buildRoboFabDistroFromSVN import buildProducts, buildDownloadPage 20 | 21 | robofabProducts = { 22 | 'RoboFab_%s_plusAllDependencies':[ 23 | ("http://svn.robofab.com/trunk", "RoboFab"), 24 | ("http://svn.typesupply.com/packages/vanilla/trunk", "Vanilla"), 25 | ("http://svn.typesupply.com/packages/dialogKit/trunk", "DialogKit"), 26 | ("https://fonttools.svn.sourceforge.net/svnroot/fonttools/trunk/", "FontTools") 27 | ], 28 | 'RoboFab_%s_plusFontTools':[ 29 | ("http://svn.robofab.com/trunk", "RoboFab"), 30 | ("https://fonttools.svn.sourceforge.net/svnroot/fonttools/trunk/", "FontTools") 31 | ], 32 | 'RoboFab_%s_only':[ 33 | ("http://svn.robofab.com/trunk", "RoboFab"), 34 | ], 35 | } 36 | 37 | filenames, revision = buildProducts(robofabProducts, buildFolder=testBuildFolder, deleteBuilds=True, verbose=False) 38 | 39 | #print "writing html" 40 | buildDownloadPage(testBuildFolder, new=filenames, changeSet=revision) 41 | 42 | #print "filenames", filenames 43 | #print "done" -------------------------------------------------------------------------------- /Tools/installFontLab/installerFunctions.py: -------------------------------------------------------------------------------- 1 | """ These are the functions we want to use in FontLab.""" 2 | 3 | import sys, os, time, platform 4 | 5 | def log(path, entry, verbose=True): 6 | """Write stuff into log files""" 7 | try: 8 | f = open(path, 'a') 9 | except IOError: 10 | print "Error writing to log." 11 | print entry 12 | return 13 | from time import localtime, strftime 14 | t = strftime("%a, %d %b %Y %H:%M:%S", localtime()) 15 | if type(entry) != str: 16 | entry = str(entry) 17 | f.write("\n"+t+" "+entry) 18 | f.close() 19 | if verbose: 20 | print entry 21 | 22 | def findSitePackages(): 23 | """Try to find the site-packages folder for the current python.""" 24 | folderName = "site-packages" 25 | paths = {} 26 | for s in sys.path: 27 | if s.find(folderName)!=-1: 28 | root = os.path.join(s.split(folderName)[0], folderName) 29 | paths[root] = True 30 | return paths.keys() 31 | 32 | def writePathFile(pathFilePath, modulePaths): 33 | """Write the *.pth file to site-packages.""" 34 | print "writing the modulePaths path to", pathFilePath 35 | try: 36 | f = open(pathFilePath, 'w') 37 | f.write("\n".join(modulePaths)) 38 | f.close() 39 | except IOError: 40 | import traceback 41 | cla, exc, trbk = sys.exc_info() 42 | excName = cla.__name__ 43 | try: 44 | excArgs = exc.__dict__["args"] 45 | except KeyError: 46 | excArgs = "" 47 | excTb = traceback.format_tb(trbk, 2) 48 | log(excName) 49 | #log(excArgs) 50 | log(excTb) 51 | 52 | -------------------------------------------------------------------------------- /Tools/installFontLab/installerScript.py: -------------------------------------------------------------------------------- 1 | # This is a automatically generated installer script for FontLab 2 | # Generated on %(timeStamp)s 3 | # scriptVersion: %(scriptVersion)s 4 | 5 | p = "%(appLogPath)s" 6 | log(p,"-" * 50) 7 | log(p,"hello, this is application: %(appName)s") 8 | log(p,"Running script version: %(scriptVersion)s") 9 | log(p,"Platform:"+platform.platform()) 10 | resultData = [] 11 | resultData.append("application:\t%(appName)s") 12 | print "I will log to", "%(appLogPath)s" 13 | print "I will save my results to", "%(resultsPath)s" 14 | print "I will test for these modules:", "%(moduleData)s" 15 | from FL import * 16 | log(p,"FontLab version "+fl.version) 17 | resultData.append("version:\t"+fl.version) 18 | 19 | installedAlready = False 20 | 21 | for moduleName, data in %(moduleData)s.items(): 22 | print "---", moduleName, data 23 | try: 24 | print "---", __import__(moduleName, globals(), locals(), [], -1) 25 | resultData.append("found:\t"+moduleName) 26 | except ImportError: 27 | resultData.append("mustLoad:\t"+moduleName) 28 | 29 | sitePackagesCandidates = findSitePackages() 30 | for candidate in findSitePackages(): 31 | resultData.append("path:\t"+candidate) 32 | log(p,"site-packages found at: "+candidate) 33 | 34 | f = open("%(resultsPath)s", 'wb') 35 | f.write("\n".join(resultData)) 36 | f.close() 37 | log(p,'done!') -------------------------------------------------------------------------------- /Tools/installFontLab/testData/dummyModules/testModule1/Lib/testModule1/__init__.py: -------------------------------------------------------------------------------- 1 | """This is a test module so we can see if we can install and import this without messing up the actual modules we need to work with.""" 2 | version = "1.0" -------------------------------------------------------------------------------- /Tools/installFontLab/testData/dummyModules/testModule2/Lib/testModule2/__init__.py: -------------------------------------------------------------------------------- 1 | """This is a test module so we can see if we can install and import this without messing up the actual modules we need to work with.""" 2 | version = "1.0" -------------------------------------------------------------------------------- /Tools/versionSniffer.py: -------------------------------------------------------------------------------- 1 | """ 2 | 3 | This script can be run as a FontLab macro. 4 | It prints version numbers of the application, python, 5 | and the contents of the relevant site-packages folder. 6 | Can be useful in finding out what you have installed where. 7 | 8 | erik@letterror.com 10_2011 9 | v 1.1 # removes assert 10 | 11 | """ 12 | 13 | try: 14 | print "\n", "-"*40 15 | from FL import* 16 | print "fontlab version", fl.version 17 | except ImportError: 18 | print "probably not in FontLab." 19 | 20 | print "\n", "-"*40 21 | import sys, os 22 | print "python version", sys.version 23 | 24 | def findSitePackages(): 25 | folderName = "site-packages" 26 | paths = {} 27 | for s in sys.path: 28 | if s.find(folderName)!=-1: 29 | root = os.path.join(s.split(folderName)[0], folderName) 30 | paths[root] = True 31 | safe = [] 32 | return paths.keys() 33 | 34 | def dumpSitePackages(root): 35 | for n in os.listdir(root): 36 | if os.path.splitext(n)[-1] == ".pth": 37 | linkPath = os.path.join(root, n) 38 | print "\n", "-"*40 39 | print "\t", n.encode('ascii') 40 | print "\t", linkPath.encode('ascii') 41 | 42 | f = open(linkPath, 'r') 43 | d = f.read() 44 | f.close() 45 | print "\tcontents:" 46 | for l in d.split("\n"): 47 | print "\t\t", l.encode("ascii") 48 | 49 | for sp in findSitePackages(): 50 | print "\n", "-"*40 51 | print "site-packages is at", sp 52 | 53 | dumpSitePackages(sp) 54 | 55 | 56 | -------------------------------------------------------------------------------- /install.py: -------------------------------------------------------------------------------- 1 | """Install script for the RoboFab Package. 2 | 3 | This script installs a _link_ to the current location 4 | of RoboFab. It does not copy anything. It also means that 5 | if you move your RoboFab folder, you'll have to run the 6 | install script again. 7 | """ 8 | 9 | 10 | from distutils.sysconfig import get_python_lib 11 | import os, sys 12 | 13 | 14 | def install(srcDir, pathFileName): 15 | sitePackDir = get_python_lib() 16 | fileName = os.path.join(sitePackDir, pathFileName + ".pth") 17 | print "Installing RoboFab: about to write a path to %r in %r..." % (srcDir, fileName) 18 | f = open(fileName, 'w') 19 | f.write(srcDir) 20 | f.close() 21 | return fileName 22 | 23 | dir = os.path.join(os.path.dirname(os.path.normpath(os.path.abspath(sys.argv[0]))), "Lib") 24 | 25 | p = install(dir, "robofab") 26 | 27 | print "Robofab is now installed." 28 | print "(Note that you have to run the install script again if you move your RoboFab folder)" 29 | --------------------------------------------------------------------------------