├── .codecov.yml
├── .github
├── FUNDING.yml
└── workflows
│ ├── build.yml
│ └── test.yml
├── .gitignore
├── .readthedocs.yaml
├── CHANGELOG.md
├── DrawBot.py
├── README.md
├── Resources
├── English.lproj
│ ├── Credits.rtf
│ ├── DrawBot.icns
│ ├── MainMenu.nib
│ │ ├── designable.nib
│ │ └── keyedobjects.nib
│ ├── drawbotPackageIcon.icns
│ ├── pythonIcon.icns
│ ├── toolbarComment.pdf
│ ├── toolbarDedent.pdf
│ ├── toolbarIndent.pdf
│ ├── toolbarRun.pdf
│ └── toolbarUncomment.pdf
├── Images
│ ├── icon_left_0.png
│ ├── icon_left_1.png
│ ├── icon_left_10.png
│ ├── icon_left_11.png
│ ├── icon_left_12.png
│ ├── icon_left_13.png
│ ├── icon_left_14.png
│ ├── icon_left_15.png
│ ├── icon_left_16.png
│ ├── icon_left_17.png
│ ├── icon_left_18.png
│ ├── icon_left_19.png
│ ├── icon_left_2.png
│ ├── icon_left_20.png
│ ├── icon_left_3.png
│ ├── icon_left_4.png
│ ├── icon_left_5.png
│ ├── icon_left_6.png
│ ├── icon_left_7.png
│ ├── icon_left_8.png
│ ├── icon_left_9.png
│ ├── icon_right_0.png
│ ├── icon_right_1.png
│ ├── icon_right_10.png
│ ├── icon_right_11.png
│ ├── icon_right_12.png
│ ├── icon_right_13.png
│ ├── icon_right_14.png
│ ├── icon_right_15.png
│ ├── icon_right_16.png
│ ├── icon_right_17.png
│ ├── icon_right_18.png
│ ├── icon_right_19.png
│ ├── icon_right_2.png
│ ├── icon_right_20.png
│ ├── icon_right_3.png
│ ├── icon_right_4.png
│ ├── icon_right_5.png
│ ├── icon_right_6.png
│ ├── icon_right_7.png
│ ├── icon_right_8.png
│ └── icon_right_9.png
└── externalTools
│ ├── ffmpeg
│ ├── gifsicle
│ ├── mkbitmap
│ └── potrace
├── app
├── codesign-app.sh
├── customWheels
│ └── README.md
├── ensure_universal_wheels.py
├── entitlements.xml
└── extract_changes.py
├── docs
├── Makefile
├── _static
│ └── .gitkeep
├── _themes
│ └── drawBotTheme
│ │ ├── layout.html
│ │ ├── relations.html
│ │ ├── search.html
│ │ ├── searchbox.html
│ │ ├── static
│ │ ├── drawBot.css_t
│ │ ├── drawBotIcon.svg
│ │ ├── drawBotURLhandler.js
│ │ ├── favicon.ico
│ │ ├── favicons
│ │ │ ├── android-chrome-192x192.png
│ │ │ ├── android-chrome-512x512.png
│ │ │ ├── apple-touch-icon.png
│ │ │ ├── browserconfig.xml
│ │ │ ├── favicon-16x16.png
│ │ │ ├── favicon-32x32.png
│ │ │ ├── favicon.ico
│ │ │ ├── mstile-150x150.png
│ │ │ ├── safari-pinned-tab.svg
│ │ │ └── site.webmanifest
│ │ ├── pygments.css
│ │ └── skeleton
│ │ │ ├── base.css
│ │ │ ├── layout.css
│ │ │ └── skeleton.css
│ │ └── theme.conf
├── conf.py
├── content
│ ├── assets
│ │ ├── drawBot.jpg
│ │ ├── drawBotApp.png
│ │ ├── packageBuilder.png
│ │ ├── preferences.png
│ │ └── variables.png
│ ├── canvas.rst
│ ├── canvas
│ │ ├── pages.rst
│ │ ├── saveImage.rst
│ │ └── state.rst
│ ├── color.rst
│ ├── color
│ │ ├── cmykFill.rst
│ │ ├── cmykStroke.rst
│ │ ├── fill.rst
│ │ └── stroke.rst
│ ├── courseware.rst
│ ├── credits.rst
│ ├── download.rst
│ ├── drawBotApp.rst
│ ├── drawBotApp
│ │ ├── codeEditor.rst
│ │ ├── drawBotPackage.rst
│ │ ├── preferences.rst
│ │ └── preview.rst
│ ├── drawBotIcon.rst
│ ├── history.rst
│ ├── image
│ │ ├── drawingImages.rst
│ │ ├── imageObject.rst
│ │ └── imageProperties.rst
│ ├── images.rst
│ ├── quickReference.rst
│ ├── shapes.rst
│ ├── shapes
│ │ ├── bezierPath.rst
│ │ ├── drawingPath.rst
│ │ ├── pathProperties.rst
│ │ └── primitives.rst
│ ├── text.rst
│ ├── text
│ │ ├── drawingText.rst
│ │ ├── formattedString.rst
│ │ └── textProperties.rst
│ └── variables.rst
├── index.rst
└── requirements.txt
├── drawBot
├── __init__.py
├── aliases.py
├── context
│ ├── __init__.py
│ ├── baseContext.py
│ ├── drawBotContext.py
│ ├── dummyContext.py
│ ├── gifContext.py
│ ├── icnsContext.py
│ ├── imageContext.py
│ ├── imageObjectContext.py
│ ├── mp4Context.py
│ ├── pdfContext.py
│ ├── printContext.py
│ ├── svgContext.py
│ └── tools
│ │ ├── SFNTLayoutTypes.py
│ │ ├── __init__.py
│ │ ├── drawBotbuiltins.py
│ │ ├── gifTools.py
│ │ ├── gifsicleLicense
│ │ ├── imageObject.py
│ │ ├── mp4Tools.py
│ │ ├── openType.py
│ │ ├── traceImage.py
│ │ └── variation.py
├── drawBotDrawingTools.py
├── drawBotPackage.py
├── drawBotPageDrawingTools.py
├── drawBotSettings.py
├── macOSVersion.py
├── misc.py
├── pipInstaller.py
├── scriptTools.py
├── ui
│ ├── __init__.py
│ ├── codeEditor.py
│ ├── debug.py
│ ├── drawBotController.py
│ ├── drawBotPackageController.py
│ ├── drawView.py
│ ├── lineNumberRulerView.py
│ ├── preferencesController.py
│ └── splitView.py
└── updater.py
├── examples
├── roundedRect.py
└── star.py
├── license.txt
├── requirements.txt
├── ruff.toml
├── scripting
├── generateDrawbotInit.py
└── imageObjectCodeExtractor.py
├── setup.py
├── setupApp.py
├── test-requirements.txt
└── tests
├── data
├── MutatorSans.ttc
├── MutatorSans.ttf
├── drawBot.bmp
├── drawBot.jpg
├── drawBot.pdf
├── drawBot.png
├── drawBot144.png
├── example_appendGlyphFormattedString.png
├── example_bezierPath.png
├── example_blendMode.png
├── example_clipPath.png
├── example_cmykFill.png
├── example_cmykLinearGradient.png
├── example_cmykRadialGradient.png
├── example_cmykShadow.png
├── example_cmykStroke.png
├── example_colorSpace.png
├── example_drawPath.png
├── example_fill.png
├── example_fontNamedInstance.png
├── example_fontVariations.png
├── example_formattedString.png
├── example_frameDuration.png
├── example_hyphenation.png
├── example_image.png
├── example_imageObject.png
├── example_indent.png
├── example_installFont.png
├── example_language.png
├── example_line.png
├── example_lineCap.png
├── example_lineDash.png
├── example_lineHeight.png
├── example_lineJoin.png
├── example_linearGradient.png
├── example_miterLimit.png
├── example_newDrawing.png
├── example_newPage.png
├── example_opacity.png
├── example_openTypeFeatures.png
├── example_openTypeFeaturesFormattedString.png
├── example_oval.png
├── example_overflowText.png
├── example_pages.png
├── example_pixelColor.png
├── example_polygon.png
├── example_printImage.png
├── example_radialGradient.png
├── example_rect.png
├── example_saveImage.png
├── example_saveImageResolutionExample.png
├── example_savedState.png
├── example_shadow.png
├── example_size.png
├── example_strikethrough.png
├── example_stroke.png
├── example_strokeWidth.png
├── example_tabs.png
├── example_tabsFormattedString.png
├── example_text.png
├── example_textBox.png
├── example_textBoxInPath.png
├── example_textRTL.png
├── example_tracking.png
├── example_underline.png
├── example_url.png
├── example_variablesUI.png
├── expected_appendGlyphWithFontVariations.pdf
├── expected_appendGlyphWithFontVariations.png
├── expected_appendGlyphWithFontVariations.svg
├── expected_appendGlyphWithTracking.pdf
├── expected_appendGlyphWithTracking.png
├── expected_appendGlyphWithTracking.svg
├── expected_booleanOperations.pdf
├── expected_booleanOperations.png
├── expected_booleanOperations.svg
├── expected_booleanOperations2.pdf
├── expected_booleanOperations2.png
├── expected_booleanOperations2.svg
├── expected_centeredTransform.pdf
├── expected_centeredTransform.png
├── expected_centeredTransform.svg
├── expected_centeredTransformBezierPath.pdf
├── expected_centeredTransformBezierPath.png
├── expected_centeredTransformBezierPath.svg
├── expected_cmykFill.pdf
├── expected_cmykFill.png
├── expected_cmykFill.svg
├── expected_cmykLinearGradient.pdf
├── expected_cmykLinearGradient.png
├── expected_cmykLinearGradient.svg
├── expected_cmykRadialGradient.pdf
├── expected_cmykRadialGradient.png
├── expected_cmykRadialGradient.svg
├── expected_dashStroke.pdf
├── expected_dashStroke.png
├── expected_dashStroke.svg
├── expected_fill.pdf
├── expected_fill.png
├── expected_fill.svg
├── expected_fontAttributes.pdf
├── expected_fontAttributes.png
├── expected_fontAttributes.svg
├── expected_fontAttributes.txt
├── expected_fontPath.pdf
├── expected_fontPath.png
├── expected_fontVariations.pdf
├── expected_fontVariations.png
├── expected_fontVariations.svg
├── expected_fontVariations.txt
├── expected_fontVariations2.pdf
├── expected_fontVariations2.png
├── expected_fontVariations2.svg
├── expected_fontVariations2.txt
├── expected_formattedStringURL.svg
├── expected_image.pdf
├── expected_image.png
├── expected_image.svg
├── expected_image2.pdf
├── expected_image2.png
├── expected_image2.svg
├── expected_image3.pdf
├── expected_image3.png
├── expected_image3.svg
├── expected_image4.pdf
├── expected_image4.png
├── expected_image4.svg
├── expected_imageAntiAliasing.png
├── expected_imageFontSubpixelQuantization.png
├── expected_imageHTTP.pdf
├── expected_imageHTTP.png
├── expected_imageHTTP.svg
├── expected_imagePixelColor.pdf
├── expected_imagePixelColor.png
├── expected_imagePixelColor.svg
├── expected_imagePixelColor.txt
├── expected_line.pdf
├── expected_line.png
├── expected_line.svg
├── expected_linearGradient.pdf
├── expected_linearGradient.png
├── expected_linearGradient.svg
├── expected_openTypeFeatures.pdf
├── expected_openTypeFeatures.png
├── expected_openTypeFeatures.svg
├── expected_openTypeFeatures.txt
├── expected_openTypeFeatures2.pdf
├── expected_openTypeFeatures2.png
├── expected_openTypeFeatures2.svg
├── expected_openTypeFeatures2.txt
├── expected_openTypeFeatures_kern.pdf
├── expected_openTypeFeatures_kern.png
├── expected_openTypeFeatures_kern.svg
├── expected_openTypeFeatures_kern.txt
├── expected_oval.pdf
├── expected_oval.png
├── expected_oval.svg
├── expected_path.pdf
├── expected_path.png
├── expected_path.svg
├── expected_pathWithCounter.pdf
├── expected_pathWithCounter.png
├── expected_pathWithCounter.svg
├── expected_polygon.pdf
├── expected_polygon.png
├── expected_polygon.svg
├── expected_radialGradient.pdf
├── expected_radialGradient.png
├── expected_radialGradient.svg
├── expected_rect.pdf
├── expected_rect.png
├── expected_rect.svg
├── expected_removeOverlap.pdf
├── expected_removeOverlap.png
├── expected_removeOverlap.svg
├── expected_save.pdf
├── expected_save.png
├── expected_save.svg
├── expected_save1.pdf
├── expected_save1.png
├── expected_save1.svg
├── expected_savedState.pdf
├── expected_savedState.png
├── expected_savedState.svg
├── expected_savedState1.pdf
├── expected_savedState1.png
├── expected_savedState1.svg
├── expected_shapes.pdf
├── expected_shapes.png
├── expected_shapes.svg
├── expected_svgLinkURL.svg
├── expected_svgMixin.svg
├── expected_svgSaveFallback.svg
├── expected_text.pdf
├── expected_text.png
├── expected_text.svg
├── expected_text2.pdf
├── expected_text2.png
├── expected_text2.svg
├── expected_textBox.pdf
├── expected_textBox.png
├── expected_textBox.svg
├── expected_textBoxLongText.pdf
├── expected_textBoxLongText.png
├── expected_textBoxLongText.svg
├── expected_traceback.pdf
├── expected_traceback.png
├── expected_traceback.svg
├── expected_traceback.txt
├── fontVariations.png
└── scriptRunnerTest.py
├── differenceBuilder.py
├── drawBotScripts
├── appendGlyphWithFontVariations.py
├── appendGlyphWithTracking.py
├── booleanOperations.py
├── booleanOperations2.py
├── centeredTransform.py
├── centeredTransformBezierPath.py
├── cmykFill.py
├── cmykLinearGradient.py
├── cmykRadialGradient.py
├── dashStroke.py
├── fill.py
├── fontAttributes.py
├── fontPath.py
├── fontVariations.py
├── fontVariations2.py
├── image.py
├── image2.py
├── image3.py
├── image4.py
├── imageHTTP.py
├── imagePixelColor.py
├── line.py
├── linearGradient.py
├── openTypeFeatures.py
├── openTypeFeatures2.py
├── openTypeFeatures_kern.py
├── oval.py
├── path.py
├── pathWithCounter.py
├── polygon.py
├── radialGradient.py
├── rect.py
├── removeOverlap.py
├── save.py
├── save1.py
├── savedState.py
├── savedState1.py
├── shapes.py
├── text.py
├── text2.py
├── textBox.py
├── textBoxLongText.py
└── traceback.py
├── package
├── empty.drawbot
│ └── lib
│ │ └── main.py
├── missingMainScript.drawbot
│ └── info.plist
└── simple.drawbot
│ ├── info.plist
│ └── lib
│ └── main.py
├── runAllTests.py
├── testAutomaticallyGeneratedCode.py
├── testExamples.py
├── testExport.py
├── testImageObject.py
├── testMisc.py
├── testPackage.py
├── testScripts.py
├── testSupport.py
└── textContextMixin.py
/.codecov.yml:
--------------------------------------------------------------------------------
1 | codecov:
2 | notify:
3 | require_ci_to_pass: yes
4 |
5 | coverage:
6 | precision: 2
7 | round: down
8 | range: "70...100"
9 |
10 | status:
11 | project: yes
12 | patch: yes
13 | changes: no
14 |
15 | parsers:
16 | gcov:
17 | branch_detection:
18 | conditional: yes
19 | loop: yes
20 | method: no
21 | macro: no
22 |
23 | comment: false
24 |
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | github: [justvanrossum, typemytype]
4 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: DrawBot Test Bench
2 |
3 | on:
4 | push:
5 | branches:
6 | - master
7 | pull_request:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | test:
13 |
14 | runs-on: macos-latest
15 |
16 | steps:
17 | - name: Checkout
18 | uses: actions/checkout@v2
19 |
20 | - name: Set up Python 3.12
21 | run: |
22 | curl https://www.python.org/ftp/python/3.12.1/python-3.12.1-macos11.pkg --output pythonInstaller.pkg
23 | sudo installer -pkg pythonInstaller.pkg -target /
24 | # Somehow using plain "python3" gives us the runner's homebrew Python,
25 | # so let's be explicit about the path:
26 | ourpython=/Library/Frameworks/Python.framework/Versions/3.12/bin/python3.12
27 | ls -l $ourpython
28 | $ourpython --version
29 | $ourpython -c "import platform; print('platform:', platform.platform())"
30 | $ourpython -c "import platform; print('macOS version:', platform.mac_ver()[0])"
31 | $ourpython -m venv venv
32 | source venv/bin/activate
33 | python -c "print('venv')"
34 | python -c "import sys; print('\n'.join(sys.path))"
35 | python -c "import platform; print('platform:', platform.platform())"
36 | python -c "import platform; print('macOS version:', platform.mac_ver()[0])"
37 |
38 | - name: Install dependencies
39 | run: |
40 | source venv/bin/activate
41 | pip install -r ./test-requirements.txt
42 | pip install .
43 | pip install codecov
44 |
45 | - name: Run MyPy on public API
46 | run: |
47 | source venv/bin/activate
48 | mypy --follow-imports=skip drawBot/drawBotDrawingTools.py
49 | mypy --follow-imports=skip drawBot/context/baseContext.py
50 | mypy --follow-imports=skip drawBot/context/tools/imageObject.py
51 |
52 | - name: Run tests
53 | run: |
54 | source venv/bin/activate
55 | coverage run ./tests/runAllTests.py
56 |
57 | - name: Storing Test Data Artifacts
58 | if: failure()
59 | uses: actions/upload-artifact@master
60 | with:
61 | name: DrawBot Temp Data Results
62 | path: ./tests/tempTestData
63 |
64 | - name: Building Test Differences
65 | if: failure()
66 | run: |
67 | source venv/bin/activate
68 | python ./tests/differenceBuilder.py ./tests/tempTestData ./tests/differences.pdf
69 |
70 | - name: Storing Test Differences
71 | if: failure()
72 | uses: actions/upload-artifact@master
73 | with:
74 | name: DrawBot Test Differences
75 | path: ./tests/differences.pdf
76 |
77 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .ruff_cache
2 | .venv
3 | .vscode
4 | *.py[cod]
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Packages
10 | *.egg
11 | *.egg-info
12 | dist
13 | build
14 | eggs
15 | parts
16 | bin
17 | var
18 | sdist
19 | develop-eggs
20 | .installed.cfg
21 |
22 |
23 | # Installer logs
24 | pip-log.txt
25 |
26 | # Unit test / coverage reports
27 | .coverage
28 | .tox
29 | nosetests.xml
30 |
31 | # Translations
32 | *.mo
33 |
34 | # Mr Developer
35 | .mr.developer.cfg
36 | .project
37 | .pydevproject
38 |
39 | *.sublime-workspace
40 | *.sublime-project
41 |
42 | docs/_build
43 | docs/downloads
44 | local
45 |
46 | *.command
47 | env/*
48 |
49 | # Finder turds
50 | .DS_Store
51 |
52 | # DrawBot tests
53 | tests/temp_data/* # obsolete
54 | tests/tempTestData/*
55 |
56 | # Virtual Environments
57 | /venv*/
58 |
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | # .readthedocs.yaml
2 | # Read the Docs configuration file
3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4 |
5 | # Required
6 | version: 2
7 |
8 | # Set the OS, Python version and other tools you might need
9 | build:
10 | os: ubuntu-22.04
11 | tools:
12 | python: "3"
13 |
14 | # Build documentation in the "docs/" directory with Sphinx
15 | sphinx:
16 | configuration: docs/conf.py
17 |
18 | # Optional but recommended, declare the Python requirements required
19 | # to build your documentation
20 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
21 | python:
22 | install:
23 | - requirements: docs/requirements.txt
--------------------------------------------------------------------------------
/Resources/English.lproj/Credits.rtf:
--------------------------------------------------------------------------------
1 | {\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf510
2 | {\fonttbl\f0\fswiss\fcharset0 Helvetica;}
3 | {\colortbl;\red255\green255\blue255;}
4 | \margl1440\margr1440\vieww9000\viewh9000\viewkind0
5 | \pard\tx720\tx1440\tx2160\tx2880\tx3600\tx4320\tx5040\tx5760\tx6480\tx7200\tx7920\tx8640\qc
6 |
7 | \f0\fs24 \cf0 DrawBot is written by Just van Rossum and Frederik Berlaen\
8 | just@letterror.com\
9 | frederik@typemytype.com\
10 | \
11 | http://www.DrawBot.com}
--------------------------------------------------------------------------------
/Resources/English.lproj/DrawBot.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/English.lproj/DrawBot.icns
--------------------------------------------------------------------------------
/Resources/English.lproj/MainMenu.nib/keyedobjects.nib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/English.lproj/MainMenu.nib/keyedobjects.nib
--------------------------------------------------------------------------------
/Resources/English.lproj/drawbotPackageIcon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/English.lproj/drawbotPackageIcon.icns
--------------------------------------------------------------------------------
/Resources/English.lproj/pythonIcon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/English.lproj/pythonIcon.icns
--------------------------------------------------------------------------------
/Resources/English.lproj/toolbarComment.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/English.lproj/toolbarComment.pdf
--------------------------------------------------------------------------------
/Resources/English.lproj/toolbarDedent.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/English.lproj/toolbarDedent.pdf
--------------------------------------------------------------------------------
/Resources/English.lproj/toolbarIndent.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/English.lproj/toolbarIndent.pdf
--------------------------------------------------------------------------------
/Resources/English.lproj/toolbarRun.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/English.lproj/toolbarRun.pdf
--------------------------------------------------------------------------------
/Resources/English.lproj/toolbarUncomment.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/English.lproj/toolbarUncomment.pdf
--------------------------------------------------------------------------------
/Resources/Images/icon_left_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_0.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_1.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_10.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_11.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_12.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_13.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_14.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_15.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_16.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_17.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_18.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_19.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_2.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_20.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_3.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_4.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_5.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_6.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_7.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_8.png
--------------------------------------------------------------------------------
/Resources/Images/icon_left_9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_left_9.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_0.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_1.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_10.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_11.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_12.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_13.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_13.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_14.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_14.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_15.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_16.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_17.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_17.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_18.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_18.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_19.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_19.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_2.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_20.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_20.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_3.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_4.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_5.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_6.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_7.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_8.png
--------------------------------------------------------------------------------
/Resources/Images/icon_right_9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/Images/icon_right_9.png
--------------------------------------------------------------------------------
/Resources/externalTools/ffmpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/externalTools/ffmpeg
--------------------------------------------------------------------------------
/Resources/externalTools/gifsicle:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/externalTools/gifsicle
--------------------------------------------------------------------------------
/Resources/externalTools/mkbitmap:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/externalTools/mkbitmap
--------------------------------------------------------------------------------
/Resources/externalTools/potrace:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/Resources/externalTools/potrace
--------------------------------------------------------------------------------
/app/codesign-app.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e # abort on errors
4 |
5 | DEV_ID=$1
6 | APP_PATH=$2
7 | ENTITLEMENTS=$3
8 |
9 | echo "start codesign..."
10 |
11 | # Explicitly codesign all embedded *.so and *.dylib files
12 | find "$APP_PATH" -iname '*.so' -or -iname '*.dylib' |
13 | while read libfile; do
14 | codesign --sign "$DEV_ID" \
15 | --entitlements "$ENTITLEMENTS" \
16 | --deep "${libfile}" \
17 | --force \
18 | --options runtime;
19 | done;
20 |
21 |
22 | codesign --sign "$DEV_ID" --entitlements "$ENTITLEMENTS" --deep "${APP_PATH}/Contents/Resources/ffmpeg" --force --options runtime
23 | codesign --sign "$DEV_ID" --entitlements "$ENTITLEMENTS" --deep "${APP_PATH}/Contents/Resources/gifsicle" --force --options runtime
24 | codesign --sign "$DEV_ID" --entitlements "$ENTITLEMENTS" --deep "${APP_PATH}/Contents/Resources/mkbitmap" --force --options runtime
25 | codesign --sign "$DEV_ID" --entitlements "$ENTITLEMENTS" --deep "${APP_PATH}/Contents/Resources/potrace" --force --options runtime
26 |
27 |
28 | # Codesign the app
29 | codesign --sign "$DEV_ID" \
30 | --entitlements "$ENTITLEMENTS" \
31 | --deep "$APP_PATH" \
32 | --force \
33 | --options runtime;
34 |
35 | echo "verify with codesign"
36 | # verify
37 | codesign --verify --verbose=4 "$APP_PATH"
38 |
39 | echo "verify with spctl"
40 | # verify with spctl
41 | spctl --verbose=4 --raw --assess --type execute "$APP_PATH"
42 |
43 | echo "Done codesign"
--------------------------------------------------------------------------------
/app/customWheels/README.md:
--------------------------------------------------------------------------------
1 | This folder contains custom wheels, because the ones on PyPI do not qualify or work when codesigning and notarizing the FontGoggles application.
2 |
3 | # lxml
4 |
5 | The official wheel blocks notarizing:
6 |
7 | "The binary uses an SDK older than the 10.9 SDK."
8 |
9 | # uharfbuzz
10 |
11 | Codesigning and notarizing works, validating the code signatures works, yet when uharfbuzz gets imported upon running the application on macOS 10.10 (maybe also others, but not 10.15) it results in an dyld ImportError, claiming that the signature is invalid. If I build uharfbuzz from the source, this does not happen. I have no idea what the difference could be.
12 |
13 | # xattr
14 |
15 | same as uharfbuzz
16 |
--------------------------------------------------------------------------------
/app/entitlements.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.cs.disable-executable-page-protection
6 |
7 | com.apple.security.cs.disable-library-validation
8 |
9 |
10 |
--------------------------------------------------------------------------------
/app/extract_changes.py:
--------------------------------------------------------------------------------
1 | import os
2 | import pathlib
3 | import re
4 |
5 |
6 | changelogVersionPattern = re.compile(r"## \[(.+)\]")
7 | githubRefPattern = re.compile(r"refs/tags/(.*)")
8 |
9 |
10 | changelogPath = pathlib.Path(__file__).resolve().parent.parent / "CHANGELOG.md"
11 | changelog = changelogPath.read_text("utf-8")
12 |
13 | m = githubRefPattern.match(os.getenv("GITHUB_REF"))
14 | version = m.group(1)
15 |
16 | notes = []
17 |
18 | collecting = False
19 | for line in changelog.splitlines():
20 | m = changelogVersionPattern.match(line)
21 | if m is not None:
22 | if collecting:
23 | break
24 | elif m.group(1) == version:
25 | collecting = True
26 | elif collecting:
27 | notes.append(line)
28 |
29 | # print("\n".join(notes).strip().replace("\n", "%0A"))
30 | print("\n".join(notes).strip())
31 |
--------------------------------------------------------------------------------
/docs/_static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/_static/.gitkeep
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/relations.html:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/_themes/drawBotTheme/relations.html
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/search.html:
--------------------------------------------------------------------------------
1 | {% extends "layout.html" %}
2 | {% set title = _('Search') %}
3 | {% set script_files = script_files + ['_static/searchtools.js'] %}
4 | {% block extrahead %}
5 |
6 |
7 |
10 | {{ super() }}
11 | {% endblock %}
12 | {% block body %}
13 |
{{ _('Search') }}
14 |
15 |
16 |
17 | {% trans %}Please activate JavaScript to enable the search
18 | functionality.{% endtrans %}
19 |
20 |
21 |
22 | {% trans %}From here you can search these documents. Enter your search
23 | words into the box below and click "search". Note that the search
24 | function will automatically search for all of the words. Pages
25 | containing fewer words won't appear in the result list.{% endtrans %}
26 |
27 | {% if search_performed %}
28 | {{ _('Search Results') }}
29 | {% if not search_results %}
30 | {{ _('Your search did not match any results.') }}
31 | {% endif %}
32 | {% endif %}
33 |
34 | {% if search_results %}
35 |
36 | {% for href, caption, context in search_results %}
37 | {{ caption }}
38 | {{ context|e }}
39 |
40 | {% endfor %}
41 |
42 | {% endif %}
43 |
44 | {% endblock %}
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/searchbox.html:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/drawBotURLhandler.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function () {
2 | $(".drawbotlink").each(function () {
3 | this.protocol = "drawbot";
4 | });
5 | });
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/_themes/drawBotTheme/static/favicon.ico
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/favicons/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/_themes/drawBotTheme/static/favicons/android-chrome-192x192.png
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/favicons/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/_themes/drawBotTheme/static/favicons/android-chrome-512x512.png
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/favicons/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/_themes/drawBotTheme/static/favicons/apple-touch-icon.png
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/favicons/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #2d89ef
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/favicons/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/_themes/drawBotTheme/static/favicons/favicon-16x16.png
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/favicons/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/_themes/drawBotTheme/static/favicons/favicon-32x32.png
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/favicons/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/_themes/drawBotTheme/static/favicons/favicon.ico
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/favicons/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/_themes/drawBotTheme/static/favicons/mstile-150x150.png
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/favicons/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Drawbot Docs",
3 | "short_name": "Drawbot Docs",
4 | "icons": [
5 | {
6 | "src": "android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "theme_color": "#ffffff",
17 | "background_color": "#ffffff",
18 | "display": "standalone"
19 | }
20 |
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/static/skeleton/layout.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Skeleton V1.2
3 | * Copyright 2011, Dave Gamache
4 | * www.getskeleton.com
5 | * Free to use under the MIT license.
6 | * http://www.opensource.org/licenses/mit-license.php
7 | * 6/20/2012
8 | */
9 |
10 | /* Table of Content
11 | ==================================================
12 | #Site Styles
13 | #Page Styles
14 | #Media Queries
15 | #Font-Face */
16 |
17 | /* #Site Styles
18 | ================================================== */
19 |
20 | /* #Page Styles
21 | ================================================== */
22 |
23 | /* #Media Queries
24 | ================================================== */
25 |
26 | /* Smaller than standard 960 (devices and browsers) */
27 | @media only screen and (max-width: 959px) {}
28 |
29 | /* Tablet Portrait size to standard 960 (devices and browsers) */
30 | @media only screen and (min-width: 768px) and (max-width: 959px) {}
31 |
32 | /* All Mobile Sizes (devices and browser) */
33 | @media only screen and (max-width: 767px) {}
34 |
35 | /* Mobile Landscape Size to Tablet Portrait (devices and browsers) */
36 | @media only screen and (min-width: 480px) and (max-width: 767px) {}
37 |
38 | /* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */
39 | @media only screen and (max-width: 479px) {}
40 |
41 |
42 | /* #Font-Face
43 | ================================================== */
44 | /* This is the proper syntax for an @font-face file
45 | Just create a "fonts" folder at the root,
46 | copy your FontName into code below and remove
47 | comment brackets */
48 |
49 | /* @font-face {
50 | font-family: 'FontName';
51 | src: url('../fonts/FontName.eot');
52 | src: url('../fonts/FontName.eot?iefix') format('eot'),
53 | url('../fonts/FontName.woff') format('woff'),
54 | url('../fonts/FontName.ttf') format('truetype'),
55 | url('../fonts/FontName.svg#webfontZam02nTh') format('svg');
56 | font-weight: normal;
57 | font-style: normal; }
58 | */
--------------------------------------------------------------------------------
/docs/_themes/drawBotTheme/theme.conf:
--------------------------------------------------------------------------------
1 | [theme]
2 | inherit = basic
3 | stylesheet = drawBot.css
4 |
5 | [options]
6 | rightsidebar = true
7 | stickysidebar = true
8 | collapsiblesidebar = true
9 | externalrefs = true
10 |
11 | bodyfont = "DBRegular", Monaco, Monospace
12 | headerfont = "DBRegular", Monaco, Monospace
13 |
14 | bgcolor = #FFFFFF
15 | textcolor = #3B3A3A
16 | linkcolor = #2CB7F2
17 | headercolor1 = #FF8400
18 | headercolor2 = #FF8400
19 | headerlinkcolor = #F2462C
20 |
21 | codebgcolor = #FFFFFF
22 | codetextcolor = #3B3A3A
--------------------------------------------------------------------------------
/docs/content/assets/drawBot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/content/assets/drawBot.jpg
--------------------------------------------------------------------------------
/docs/content/assets/drawBotApp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/content/assets/drawBotApp.png
--------------------------------------------------------------------------------
/docs/content/assets/packageBuilder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/content/assets/packageBuilder.png
--------------------------------------------------------------------------------
/docs/content/assets/preferences.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/content/assets/preferences.png
--------------------------------------------------------------------------------
/docs/content/assets/variables.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/docs/content/assets/variables.png
--------------------------------------------------------------------------------
/docs/content/canvas.rst:
--------------------------------------------------------------------------------
1 | Canvas
2 | ======
3 |
4 | The canvas is the thing DrawBot draws on. It's the document size, the art board. It has a height and a width which can be set. The dimensions of the canvas are not related to the size of the window.
5 |
6 | .. toctree::
7 | :titlesonly:
8 | :glob:
9 |
10 | canvas/pages
11 | canvas/state
12 | canvas/saveImage
--------------------------------------------------------------------------------
/docs/content/canvas/pages.rst:
--------------------------------------------------------------------------------
1 | Pages
2 | =====
3 |
4 | **The origin of the drawing board is at the bottom left.**
5 |
6 | .. autofunction:: drawBot.newPage
7 | .. autofunction:: drawBot.newDrawing
8 | .. autofunction:: drawBot.endDrawing
9 |
10 | Size
11 | ----
12 |
13 | .. autofunction:: drawBot.size
14 | .. autofunction:: drawBot.sizes
15 |
16 | Page Attributes
17 | ---------------
18 |
19 | .. autofunction:: drawBot.width
20 | .. autofunction:: drawBot.height
21 | .. autofunction:: drawBot.pageCount
22 | .. autofunction:: drawBot.pages
23 | .. autofunction:: drawBot.frameDuration
24 | .. autofunction:: drawBot.linkURL(url, (x, y, w, h))
25 | .. autofunction:: drawBot.linkRect(name, (x, y, w, h))
26 | .. autofunction:: drawBot.linkDestination(name, (x, y))
27 |
--------------------------------------------------------------------------------
/docs/content/canvas/saveImage.rst:
--------------------------------------------------------------------------------
1 | Saving
2 | ======
3 |
4 | .. autofunction:: drawBot.saveImage(paths, **options)
5 | .. autofunction:: drawBot.printImage
6 | .. autofunction:: drawBot.pdfImage
--------------------------------------------------------------------------------
/docs/content/canvas/state.rst:
--------------------------------------------------------------------------------
1 | Transformations
2 | ===============
3 |
4 | .. autofunction:: drawBot.translate
5 | .. autofunction:: drawBot.rotate
6 | .. autofunction:: drawBot.scale
7 | .. autofunction:: drawBot.skew
8 | .. autofunction:: drawBot.transform((xx, xy, yx, yy, x, y))
9 |
10 | Managing the Graphics State
11 | ---------------------------
12 |
13 | .. autofunction:: drawBot.savedState
14 | .. autofunction:: drawBot.save
15 | .. autofunction:: drawBot.restore
16 |
--------------------------------------------------------------------------------
/docs/content/color.rst:
--------------------------------------------------------------------------------
1 | Colors
2 | ======
3 |
4 | .. toctree::
5 | :titlesonly:
6 |
7 | color/fill
8 | color/stroke
9 | color/cmykFill
10 | color/cmykStroke
11 |
12 | Opacity
13 | -------
14 |
15 | .. autofunction:: drawBot.opacity
16 |
17 | Color Blend
18 | -----------
19 |
20 | .. autofunction:: drawBot.blendMode
21 |
22 | Color Spaces
23 | ------------
24 |
25 | Set a `colorSpace` before setting a color. Color spaces are only aviable for RGB colors.
26 |
27 | .. autofunction:: drawBot.colorSpace
28 | .. autofunction:: drawBot.listColorSpaces
--------------------------------------------------------------------------------
/docs/content/color/cmykFill.rst:
--------------------------------------------------------------------------------
1 | CMYK Fill
2 | =========
3 |
4 | Set a `fill` before drawing a shape.
5 | A cmyk color used while exporting to a .pdf or an image.
6 | Handy if the file is used for print.
7 |
8 | .. autofunction:: drawBot.cmykFill
9 | .. autofunction:: drawBot.cmykLinearGradient
10 | .. autofunction:: drawBot.cmykRadialGradient
11 | .. autofunction:: drawBot.cmykShadow
12 |
--------------------------------------------------------------------------------
/docs/content/color/cmykStroke.rst:
--------------------------------------------------------------------------------
1 | CMYK Stroke
2 | ===========
3 |
4 | Set a `stroke` before drawing a shape.
5 | A cmyk color used while exporting to a .pdf or an image.
6 | Handy if the file is used for print.
7 |
8 | .. autofunction:: drawBot.cmykStroke
--------------------------------------------------------------------------------
/docs/content/color/fill.rst:
--------------------------------------------------------------------------------
1 | Fill
2 | ====
3 |
4 | Set a `fill` before drawing a shape.
5 |
6 | .. autofunction:: drawBot.fill
7 | .. autofunction:: drawBot.linearGradient
8 | .. autofunction:: drawBot.radialGradient
9 | .. autofunction:: drawBot.shadow
10 |
11 |
--------------------------------------------------------------------------------
/docs/content/color/stroke.rst:
--------------------------------------------------------------------------------
1 | Stroke
2 | ======
3 |
4 | Set a `stroke` before drawing a shape.
5 |
6 | .. autofunction:: drawBot.stroke
--------------------------------------------------------------------------------
/docs/content/credits.rst:
--------------------------------------------------------------------------------
1 | Credits
2 | =======
3 |
4 | Thanks to Python_ and PyObjC_ for making this possible and `Tal Leming`_ for wrapping PyObjC_ in vanilla_.
5 |
6 | A tip of the hat to `John Maeda`_ for showing the way with `Design By Numbers`_, Casey Reas and Ben Fry, the folks from Processing_.
7 |
8 | Finally thanks for the support and feedback from the users!
9 |
10 | Thanks Andy for the :doc:`icon`!
11 |
12 | .. _Python: http://www.python.org/
13 | .. _PyObjC: http://pythonhosted.org/pyobjc/
14 | .. _John Maeda: http://www.maedastudio.com/
15 | .. _Design By Numbers: http://dbn.media.mit.edu
16 | .. _Processing: http://www.processing.org
17 | .. _Tal Leming: http://www.typesupply.com/
18 | .. _vanilla: https://github.com/typesupply/vanilla/
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/docs/content/download.rst:
--------------------------------------------------------------------------------
1 | Download
2 | ========
3 |
4 | .. cssclass:: app-download-link
5 |
6 | > `Download DrawBot `_
7 |
8 |
9 | requirements: osX 10.12+
10 |
11 | Older Downloads
12 | ---------------
13 |
14 | `Version History `_
15 |
16 | `Very Old Version History `_
17 |
18 | License
19 | -------
20 |
21 | .. include:: /../license.txt
22 |
--------------------------------------------------------------------------------
/docs/content/drawBotApp.rst:
--------------------------------------------------------------------------------
1 | DrawBot App
2 | ===========
3 |
4 | .. image:: assets/drawBotApp.png
5 |
6 | Drawbot has three main views:
7 |
8 | * A :doc:`drawBotApp/codeEditor`: the place to write code.
9 | * An Output View for `print` statements and tracebacks (reports for when your script fails).
10 | * The :doc:`drawBotApp/preview` will preview the current page – and all generated pages, in the case of documents with multiple pages.
11 |
12 | The :doc:`drawBotApp/preferences` window contains some settings related to the appearance of the DrawBot editor.
13 |
14 | .. toctree::
15 | :titlesonly:
16 | :hidden:
17 |
18 | drawBotApp/codeEditor
19 | drawBotApp/preview
20 | drawBotApp/preferences
21 | drawBotApp/drawBotPackage
--------------------------------------------------------------------------------
/docs/content/drawBotApp/codeEditor.rst:
--------------------------------------------------------------------------------
1 | Code Editor
2 | ===========
3 |
4 | The place where you can tell Python to draw things on the page and/or print things in the console.
5 |
6 | The syntax colors can be customized in the :doc:`preferences` window.
7 |
8 | Code interaction
9 | ----------------
10 |
11 | The code editor also makes it easy and fun to interact with values in your program. When selected, some kinds of Python objects can be modified dynamically by pressing the Cmd key. The effects depend on the type of object:
12 |
13 | - `bool`: select and Cmd-click to turn the value on/off like a switch.
14 | - `int` or `float`: select the number, press Cmd and move the mouse up/down or right/left to increase/decrease the number. The default step is 1, by pressing alt the step is changed to 0.1. Additional shift can be pressed to multiply the steps by 10. Using the arrow keys also works.
15 | - in `tuples` with numbers it is possible to select two neighbouring numbers and modify them together at the same time – this is specially useful when working with coordinate pairs or dimensions.
16 |
17 | .. raw:: html ::
18 |
19 |
20 |
21 | Live coding
22 | -----------
23 |
24 | The live coding mode executes the code as you type, so you can see changes without having to re-run the program every time. This is useful when working with text or making demonstrations.
25 |
26 | This feature can be turned on/off in the Python menu.
27 |
28 | Use it with caution: depending on the size of your program and the amount of interaction, Drawbot can get a bit slow.
--------------------------------------------------------------------------------
/docs/content/drawBotApp/drawBotPackage.rst:
--------------------------------------------------------------------------------
1 | DrawBot Package
2 | ===============
3 |
4 | A `.drawbot` package is a DrawBot app readable file containing python files.
5 | Making it easy to share and exchange drawbot scripts.
6 |
7 | Use a .drawbot package
8 | ----------------------
9 |
10 | Double click the or drop the .drawbot file on top of DrawBot.
11 |
12 | Build a .drawbot package
13 | ------------------------
14 |
15 | Use the build in package builder to build a `.drawbot` package.
16 |
17 | .. image:: ../assets/packageBuilder.png
18 |
19 |
20 | drawBot package specification
21 | ------------------------------
22 |
23 | A `.drawbot` package is a folder with an extension.
24 |
25 | .. code-block:: console
26 |
27 | .drawbot (package)
28 | info.plist
29 | lib/
30 | main.py
31 | anotherScript.py
32 | anImage.jpg
33 | ...
34 |
35 |
36 | The info plist dictionary can have the following keywords:
37 |
38 | * `name`: optional, default to .drawBot
39 | * `version`: optional, default to 0.0, but advised to set
40 | * `developer`: optional, default to None
41 | * `developerURL`: optional, default to None
42 | * `requiresVersion`: optional, default to all versions
43 | * `mainScript`: optional, default to 'lib/main.py' if this isn't specified?)
44 |
45 |
--------------------------------------------------------------------------------
/docs/content/drawBotApp/preferences.rst:
--------------------------------------------------------------------------------
1 | Preferences
2 | ===========
3 |
4 | The Preferences window offers fine-grained control over the code editor's syntax colors and font.
5 |
6 | .. image:: ../assets/preferences.png
7 |
8 | Additional options include turning the animation of the icon and the auto-update feature on/off.
--------------------------------------------------------------------------------
/docs/content/drawBotApp/preview.rst:
--------------------------------------------------------------------------------
1 | Preview
2 | =======
3 |
4 | The Preview area is where your generated graphics are displayed.
5 |
6 | Current page
7 | ------------
8 |
9 | The main preview area shows the drawing canvas or current page.
10 |
11 | The zoom level can be increased with `Cmd+` and decreased with `Cmd-`.
12 |
13 | In case of multi-page documents, the visualization settings can be changed by right-clicking on the page and choosing between single or double pages and continuous or individual.
14 |
15 | Pages overview
16 | --------------
17 |
18 | Besides the current page there is also a secondary pane to the left where all pages can be seen at once (in case of multi-page documents). This pane is hidden by default, and can be opened by pulling the vertical division to the right.
19 |
--------------------------------------------------------------------------------
/docs/content/history.rst:
--------------------------------------------------------------------------------
1 | History
2 | =======
3 |
4 | The DrawBot project started in 2003 as a program named "DesignRobots", written for the occasion of a Python workshop at the TypoTechnica conference. Since then the application evolved into a Cocoa application with a powerful API and image export functionality.
5 |
6 | Version 0.9a
7 | ------------
8 |
9 | First release as Cocoa application. Supports rectangles, ovals, bezier paths, but not text.
10 | Unofficial Fork of Version 0.9a
11 |
12 | There is an unofficial forked version of DrawBot around. Unfortunately this version does not document the differences with the current DrawBot. This has led to considerable confusion and frustration with users.
13 |
14 | Version 2.0
15 | -----------
16 |
17 | In use at the TypeMedia department of the Royal Academy in The Hague for about then 10 years!. Many Improvements on the API and text support. (2007)
18 |
19 | Version 3+
20 | ----------
21 |
22 | Complete rewritten and many improvements on the API.
23 |
24 |
--------------------------------------------------------------------------------
/docs/content/image/drawingImages.rst:
--------------------------------------------------------------------------------
1 | Drawing Images
2 | ==============
3 |
4 | .. autofunction:: drawBot.image(path, (x, y), alpha=1, pageNumber=None)
5 |
--------------------------------------------------------------------------------
/docs/content/image/imageObject.rst:
--------------------------------------------------------------------------------
1 | Image Objects
2 | =============
3 |
4 | .. autoclass:: drawBot.ImageObject
5 | :members:
--------------------------------------------------------------------------------
/docs/content/image/imageProperties.rst:
--------------------------------------------------------------------------------
1 | Image Properties
2 | ================
3 |
4 | .. autofunction:: drawBot.imageSize(path)
5 | .. autofunction:: drawBot.imagePixelColor(path, (x, y))
6 | .. autofunction:: drawBot.imageResolution(path)
7 | .. autofunction:: drawBot.numberOfPages(path)
8 |
--------------------------------------------------------------------------------
/docs/content/images.rst:
--------------------------------------------------------------------------------
1 | Images
2 | ======
3 |
4 | .. toctree::
5 | :titlesonly:
6 | :glob:
7 |
8 | image/drawingImages
9 | image/imageProperties
10 | image/imageObject
--------------------------------------------------------------------------------
/docs/content/shapes.rst:
--------------------------------------------------------------------------------
1 | Shapes
2 | ========
3 |
4 | Different shapes and how to make them.
5 |
6 | .. toctree::
7 | :titlesonly:
8 | :glob:
9 |
10 | shapes/primitives
11 | shapes/drawingPath
12 | shapes/pathProperties
13 | shapes/bezierPath
--------------------------------------------------------------------------------
/docs/content/shapes/bezierPath.rst:
--------------------------------------------------------------------------------
1 | Bezier Paths
2 | ============
3 |
4 | .. autoclass:: drawBot.BezierPath
5 | :members:
6 | :undoc-members:
7 | :inherited-members:
8 | :show-inheritance:
9 | :exclude-members: copyContextProperties, add_note, args, with_traceback, log, MissingComponentError, svgClass, svgID, svgLink
--------------------------------------------------------------------------------
/docs/content/shapes/drawingPath.rst:
--------------------------------------------------------------------------------
1 | Drawing Paths
2 | =============
3 |
4 | Using bezier paths.
5 |
6 | .. autofunction:: drawBot.newPath
7 | .. autofunction:: drawBot.moveTo
8 | .. autofunction:: drawBot.lineTo
9 | .. autofunction:: drawBot.curveTo
10 | .. autofunction:: drawBot.qCurveTo
11 | .. autofunction:: drawBot.arc
12 | .. autofunction:: drawBot.arcTo
13 | .. autofunction:: drawBot.closePath
14 | .. autofunction:: drawBot.drawPath
15 | .. autofunction:: drawBot.clipPath
--------------------------------------------------------------------------------
/docs/content/shapes/pathProperties.rst:
--------------------------------------------------------------------------------
1 | Path Properties
2 | ===============
3 |
4 | .. autofunction:: drawBot.strokeWidth
5 | .. autofunction:: drawBot.miterLimit
6 | .. autofunction:: drawBot.lineJoin
7 | .. autofunction:: drawBot.lineCap
8 | .. autofunction:: drawBot.lineDash
--------------------------------------------------------------------------------
/docs/content/shapes/primitives.rst:
--------------------------------------------------------------------------------
1 | Primitives
2 | ==========
3 |
4 | .. autofunction:: drawBot.rect
5 | .. autofunction:: drawBot.oval
6 | .. autofunction:: drawBot.line((x1, y1), (x2, y2)))
7 | .. autofunction:: drawBot.polygon((x1, y1), (x2, y2), ..., close=True)
--------------------------------------------------------------------------------
/docs/content/text.rst:
--------------------------------------------------------------------------------
1 | Text
2 | ====
3 |
4 | .. toctree::
5 | :titlesonly:
6 | :glob:
7 |
8 | text/drawingText
9 | text/textProperties
10 | text/formattedString
--------------------------------------------------------------------------------
/docs/content/text/drawingText.rst:
--------------------------------------------------------------------------------
1 | Drawing Text
2 | ============
3 |
4 | .. autofunction:: drawBot.text(txt, (x, y), align=None)
5 | .. autofunction:: drawBot.textBox(text, (x, y, w, y), align=None)
6 |
7 | Helpers
8 | -------
9 |
10 | .. autofunction:: drawBot.textSize
11 | .. autofunction:: drawBot.textOverflow
12 | .. autofunction:: drawBot.textBoxBaselines
13 | .. autofunction:: drawBot.textBoxCharacterBounds
14 | .. autofunction:: drawBot.installedFonts
15 | .. autofunction:: drawBot.installFont
16 | .. autofunction:: drawBot.uninstallFont
17 |
--------------------------------------------------------------------------------
/docs/content/text/formattedString.rst:
--------------------------------------------------------------------------------
1 | Formatted Strings
2 | =================
3 |
4 | .. autoclass:: drawBot.FormattedString(txt=None, font=None, fontSize=10, fallbackFont=None, fill=(0, 0, 0), cmykFill=None, stroke=None, cmykStroke=None, strokeWidth=1, align=None, lineHeight=None, tracking=None, baselineShift=None, openTypeFeatures=None, tabs=None, language=None, indent=None, tailIndent=None, firstLineIndent=None, paragraphTopSpacing=None, paragraphBottomSpacing=None)
5 | :members:
6 | :undoc-members:
7 | :inherited-members:
8 | :show-inheritance:
9 | :exclude-members: copyContextProperties, svgClass, svgID, svgLink
--------------------------------------------------------------------------------
/docs/content/text/textProperties.rst:
--------------------------------------------------------------------------------
1 | Text Properties
2 | ===============
3 |
4 | .. autofunction:: drawBot.font
5 | .. autofunction:: drawBot.fontSize
6 | .. autofunction:: drawBot.fallbackFont
7 | .. autofunction:: drawBot.underline
8 | .. autofunction:: drawBot.strikethrough
9 | .. autofunction:: drawBot.hyphenation
10 | .. autofunction:: drawBot.lineHeight
11 | .. autofunction:: drawBot.tracking
12 | .. autofunction:: drawBot.baselineShift
13 | .. autofunction:: drawBot.openTypeFeatures(frac=True, case=True, ...)
14 | .. autofunction:: drawBot.listOpenTypeFeatures
15 | .. autofunction:: drawBot.fontVariations(wdth=0.6, wght=0.1, ...)
16 | .. autofunction:: drawBot.listFontVariations
17 | .. autofunction:: drawBot.fontNamedInstance
18 | .. autofunction:: drawBot.listNamedInstances
19 | .. autofunction:: drawBot.tabs
20 | .. autofunction:: drawBot.language
21 | .. autofunction:: drawBot.textProperties
22 |
23 | Font Properties
24 | ---------------
25 |
26 | .. autofunction:: drawBot.fontContainsCharacters
27 | .. autofunction:: drawBot.fontContainsGlyph
28 | .. autofunction:: drawBot.fontFilePath
29 | .. autofunction:: drawBot.listFontGlyphNames
30 | .. autofunction:: drawBot.fontDescender
31 | .. autofunction:: drawBot.fontAscender
32 | .. autofunction:: drawBot.fontXHeight
33 | .. autofunction:: drawBot.fontCapHeight
34 | .. autofunction:: drawBot.fontLeading
35 | .. autofunction:: drawBot.fontLineHeight
36 |
37 | .. downloadcode:: fontMetrics.py
38 |
39 | txt = "Hello World"
40 | x, y = 10, 100
41 |
42 | # set a font
43 | font("Helvetica")
44 | # set a font size
45 | fontSize(100)
46 | # draw the text
47 | text(txt, (x, y))
48 |
49 | # calculate the size of the text
50 | textWidth, textHeight = textSize(txt)
51 |
52 | # set a red stroke color
53 | stroke(1, 0, 0)
54 | # loop over all font metrics
55 | for metric in (0, fontDescender(), fontAscender(), fontXHeight(), fontCapHeight()):
56 | # draw a red line with the size of the drawn text
57 | line((x, y+metric), (x+textWidth, y+metric))
58 |
59 |
--------------------------------------------------------------------------------
/docs/content/variables.rst:
--------------------------------------------------------------------------------
1 | Variables
2 | =========
3 |
4 | .. autofunction:: drawBot.Variable
--------------------------------------------------------------------------------
/docs/index.rst:
--------------------------------------------------------------------------------
1 | .. highlight:: python
2 | :linenothreshold: 5
3 |
4 | .. toctree::
5 | :hidden:
6 |
7 | DrawBot Documentation
8 | =====================
9 |
10 | DrawBot is a powerful, free application for MacOSX that invites you to write simple Python scripts to generate two-dimensional graphics. The builtin graphics primitives support rectangles, ovals, (bezier) paths, polygons, text objects and transparency.
11 |
12 | Education
13 | ---------
14 |
15 | DrawBot is an ideal tool to teach the basics of programming. Students get colorful graphic treats while getting familiar with variables, conditional statements, functions and what have you. Results can be saved in a selection of different file formats, including as high resolution, scaleable PDF, svg, movie, png, jpeg, tiff...
16 |
17 | DrawBot has proven itself as part of the curriculum at selected courses at the Royal Academy in The Hague.
18 |
19 | Python
20 | ------
21 |
22 | DrawBot is written in Python_. The binary download is fully self-contained (ie. it doesn't need a Python install around), but the `source code`_ is available if you want to roll your own.
23 |
24 |
25 | .. toctree::
26 | :titlesonly:
27 | :hidden:
28 |
29 | content/shapes
30 | content/color
31 | content/canvas
32 | content/text
33 | content/images
34 | content/variables
35 | content/quickReference
36 |
37 | .. toctree::
38 | :titlesonly:
39 | :hidden:
40 |
41 | content/drawBotApp
42 | content/download
43 | content/drawBotIcon
44 |
45 | .. toctree::
46 | :titlesonly:
47 | :hidden:
48 |
49 | content/courseware
50 | content/history
51 | content/credits
52 |
53 |
54 | .. _Python: http://www.python.org/
55 | .. _source code: https://github.com/typemytype/drawbot/
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | sphinx==8.1.3
2 | fonttools
--------------------------------------------------------------------------------
/drawBot/aliases.py:
--------------------------------------------------------------------------------
1 | import os
2 | from typing import Sequence
3 |
4 | Size = tuple[int, int]
5 | Point = tuple[float, float]
6 | Points = Sequence[Point]
7 | SomePath = os.PathLike | str
8 | CMYKColor = float | tuple[float, ...]
9 | RGBAColorTuple = tuple[float, float, float, float]
10 | CMYKColorTuple = tuple[float, float, float, float]
11 | RGBColorTuple = tuple[float, float, float]
12 | RGBColor = float | tuple[float, ...]
13 | BoundingBox = tuple[float, float, float, float]
14 | TransformTuple = tuple[float, float, float, float, float, float]
15 |
--------------------------------------------------------------------------------
/drawBot/context/__init__.py:
--------------------------------------------------------------------------------
1 | from .gifContext import GIFContext
2 | from .icnsContext import ICNSContext
3 | from .imageContext import BMPContext, JPEGContext, PNGContext, TIFFContext
4 | from .imageObjectContext import NSImageContext, PILContext
5 | from .mp4Context import MP4Context
6 | from .pdfContext import PDFContext
7 | from .printContext import PrintContext
8 | from .svgContext import SVGContext
9 |
10 | allContexts = [
11 | PDFContext,
12 | PNGContext,
13 | JPEGContext,
14 | TIFFContext,
15 | SVGContext,
16 | GIFContext,
17 | BMPContext,
18 | MP4Context,
19 | ICNSContext,
20 | PrintContext,
21 | PILContext,
22 | NSImageContext,
23 | ]
24 |
25 |
26 | def subscribeContext(context):
27 | for ctx in list(allContexts):
28 | if ctx.__name__ == context.__name__:
29 | allContexts.remove(ctx)
30 | allContexts.append(context)
31 |
32 |
33 | def getContextForFileExt(ext):
34 | for context in allContexts:
35 | if ext in context.fileExtensions:
36 | return context()
37 | return None
38 |
39 |
40 | def getContextOptions():
41 | options = set()
42 | for context in allContexts:
43 | for key, _ in context.saveImageOptions:
44 | options.add(key)
45 | return options
46 |
47 |
48 | def getFileExtensions() -> list[str]:
49 | extensions = []
50 | for context in allContexts:
51 | for ext in context.fileExtensions:
52 | if ext not in extensions:
53 | extensions.append(ext)
54 | return extensions
55 |
56 |
57 | def getContextOptionsDocs(formatter="* `%s`: %s") -> list[str]:
58 | docs = []
59 | for context in allContexts:
60 | if context.saveImageOptions:
61 | ext = ", ".join(context.fileExtensions)
62 | docs.append("*%s options:*" % ext)
63 | docs.append("")
64 | for key, doc in context.saveImageOptions:
65 | docs.append(formatter % (key, doc))
66 | docs.append("")
67 | return docs
68 |
--------------------------------------------------------------------------------
/drawBot/context/drawBotContext.py:
--------------------------------------------------------------------------------
1 | import Quartz # type: ignore
2 |
3 | from .pdfContext import PDFContext
4 |
5 |
6 | class DrawBotContext(PDFContext):
7 | def getNSPDFDocument(self):
8 | if not self._hasContext:
9 | return None
10 | Quartz.CGPDFContextEndPage(self._pdfContext)
11 | Quartz.CGPDFContextClose(self._pdfContext)
12 | doc = Quartz.PDFDocument.alloc().initWithData_(self._pdfData)
13 | self._hasContext = False
14 | self._pdfContext = None
15 | self._pdfData = None
16 | return doc
17 |
--------------------------------------------------------------------------------
/drawBot/context/dummyContext.py:
--------------------------------------------------------------------------------
1 | from .baseContext import BaseContext
2 |
3 |
4 | class DummyContext(BaseContext):
5 | pass
6 |
--------------------------------------------------------------------------------
/drawBot/context/gifContext.py:
--------------------------------------------------------------------------------
1 | import tempfile
2 |
3 | import Quartz # type: ignore
4 |
5 | from .imageContext import ImageContext, getSaveImageOptions
6 | from .tools.gifTools import generateGif
7 |
8 |
9 | class GIFContext(ImageContext):
10 | fileExtensions = ["gif"]
11 |
12 | saveImageOptions = getSaveImageOptions(
13 | [
14 | "imageGIFDitherTransparency",
15 | "imageGIFRGBColorTable",
16 | "imageColorSyncProfileData",
17 | ]
18 | )
19 | saveImageOptions.append(("imageGIFLoop", "Boolean that indicates whether the animated gif should loop"))
20 |
21 | _delay = 10
22 |
23 | def __init__(self):
24 | super(GIFContext, self).__init__()
25 | self._delayData = []
26 |
27 | def _frameDuration(self, seconds):
28 | # gifsicle -h: Set frame delay to TIME (in 1/100sec).
29 | self._delayData[-1] = int(seconds * 100)
30 |
31 | def _newPage(self, width, height):
32 | super(GIFContext, self)._newPage(width, height)
33 | self._delayData.append(self._delay)
34 |
35 | def _writeDataToFile(self, data, path, options):
36 | pdfDocument = Quartz.PDFDocument.alloc().initWithData_(data)
37 | pageCount = pdfDocument.pageCount()
38 | shouldBeAnimated = pageCount > 1
39 |
40 | tempPath = path
41 | if shouldBeAnimated:
42 | options["multipage"] = True
43 | tempPath = tempfile.mkstemp(suffix=".gif")[1]
44 |
45 | self._inputPaths = []
46 | super()._writeDataToFile(data, tempPath, options)
47 |
48 | if shouldBeAnimated:
49 | generateGif(self._inputPaths, path, self._delayData, options.get("imageGIFLoop", True))
50 | del self._inputPaths
51 |
52 | def _storeImageData(self, imageData, imagePath):
53 | super()._storeImageData(imageData, imagePath)
54 | self._inputPaths.append(imagePath)
55 |
--------------------------------------------------------------------------------
/drawBot/context/icnsContext.py:
--------------------------------------------------------------------------------
1 | import os
2 | import shutil
3 | import tempfile
4 |
5 | import Quartz # type: ignore
6 |
7 | from drawBot.context.imageContext import ImageContext
8 | from drawBot.misc import DrawBotError, executeExternalProcess
9 |
10 |
11 | class ICNSContext(ImageContext):
12 | fileExtensions = ["icns"]
13 |
14 | allowedPageSizes = [16, 32, 128, 256, 512, 1024]
15 |
16 | def _writeDataToFile(self, data, path, options):
17 | # create a iconset folder
18 | iconsetPath = tempfile.mkdtemp(suffix=".iconset")
19 | try:
20 | # get the complete pdf
21 | pdfDocument = Quartz.PDFDocument.alloc().initWithData_(data)
22 | pageCount = pdfDocument.pageCount()
23 | # set the image resolution
24 | options["imageResolution"] = 72
25 | # make a copy and alter the resolution
26 | options_2x = dict(options)
27 | options_2x["imageResolution"] = 144
28 | # start loop over all pages
29 | for index in range(pageCount):
30 | # get the pdf page
31 | page = pdfDocument.pageAtIndex_(index)
32 | # get the pdf page, this acts also as pdf document...
33 | pageData = page.dataRepresentation()
34 | # extract the size of the page
35 | _, (w, h) = page.boundsForBox_(Quartz.kPDFDisplayBoxArtBox)
36 | w = int(round(w))
37 | h = int(round(h))
38 | # dont allow any other size, the command iconutil will not work otherwise
39 | if w not in self.allowedPageSizes or w != h:
40 | raise DrawBotError(
41 | "The .icns can not be build with the size '%sx%s'. Must be either: %s"
42 | % (w, h, ", ".join(["%sx%s" % (i, i) for i in self.allowedPageSizes]))
43 | )
44 | # generate a 72 dpi png in the iconset path
45 | pngPath = os.path.join(iconsetPath, "icon_%sx%s.png" % (w, h))
46 | super(ICNSContext, self)._writeDataToFile(pageData, pngPath, options)
47 | # generate a 144 dpi png in the iconset path
48 | pngPath_2x = os.path.join(iconsetPath, "icon_%sx%s@2x.png" % (w, h))
49 | super(ICNSContext, self)._writeDataToFile(pageData, pngPath_2x, options_2x)
50 | # collect all iconutil commands
51 | cmds = [
52 | "iconutil",
53 | "--convert",
54 | "icns",
55 | "--output",
56 | path,
57 | iconsetPath,
58 | ]
59 | # execute the commands
60 | stdout, stderr = executeExternalProcess(cmds)
61 | finally:
62 | # always remove the iconset
63 | shutil.rmtree(iconsetPath)
64 |
--------------------------------------------------------------------------------
/drawBot/context/imageObjectContext.py:
--------------------------------------------------------------------------------
1 | import io
2 |
3 | import AppKit # type: ignore
4 |
5 | try:
6 | from PIL import Image
7 |
8 | hasPIL = True
9 | except ImportError:
10 | hasPIL = False
11 |
12 | from drawBot.misc import DrawBotError
13 |
14 | from .imageContext import ImageContext
15 |
16 |
17 | class BaseImageObjectContext(ImageContext):
18 | def _writeDataToFile(self, data, path, options):
19 | self._imageObjects = []
20 | # we just need a path with a file extension
21 | # nothing will be written to disk
22 | super()._writeDataToFile(data, "temp.tiff", options)
23 | imageObjects = self._imageObjects
24 | del self._imageObjects
25 | if not options.get("multipage"):
26 | imageObjects = imageObjects[0]
27 | return imageObjects
28 |
29 | def _storeImageData(self, imageData, imagePath):
30 | obj = self._getObjectForData(imageData)
31 | self._imageObjects.append(obj)
32 |
33 | def _getObjectForData(self, data):
34 | raise NotImplementedError
35 |
36 |
37 | class PILContext(BaseImageObjectContext):
38 | fileExtensions = ["PIL"]
39 |
40 | def __init__(self):
41 | if not hasPIL:
42 | raise DrawBotError("The package PIL is required.")
43 | super().__init__()
44 |
45 | def _getObjectForData(self, data):
46 | file = io.BytesIO(data.bytes())
47 | return Image.open(file)
48 |
49 |
50 | class NSImageContext(BaseImageObjectContext):
51 | fileExtensions = ["NSImage"]
52 |
53 | def _getObjectForData(self, data):
54 | return AppKit.NSImage.alloc().initWithData_(data)
55 |
--------------------------------------------------------------------------------
/drawBot/context/mp4Context.py:
--------------------------------------------------------------------------------
1 | import os
2 | import shutil
3 | import tempfile
4 |
5 | from drawBot.misc import warnings
6 |
7 | from .imageContext import PNGContext
8 | from .tools.mp4Tools import generateMP4
9 |
10 |
11 | class MP4Context(PNGContext):
12 | fileExtensions = ["mp4"]
13 |
14 | saveImageOptions = [
15 | (
16 | "ffmpegCodec",
17 | "The codec to be used by ffmpeg. By default it is 'libx264' (for H.264). The 'mpeg4' codec gives better results when importing the movie into After Effects, at the expense of a larger file size.",
18 | ),
19 | ]
20 | saveImageOptions.extend((key, doc) for key, doc in PNGContext.saveImageOptions if key != "multipage")
21 |
22 | _defaultFrameDuration = 1 / 10
23 |
24 | ensureEvenPixelDimensions = True
25 |
26 | def __init__(self):
27 | super(MP4Context, self).__init__()
28 | self._frameDurations = []
29 |
30 | def _frameDuration(self, frameDuration):
31 | self._frameDurations[-1] = frameDuration
32 |
33 | def _newPage(self, width, height):
34 | super(MP4Context, self)._newPage(width, height)
35 | self._frameDurations.append(self._defaultFrameDuration)
36 | # https://github.com/typemytype/drawbot/issues/391
37 | # draw a solid white background by default
38 | # ffmpeg converts transparency to a black background color
39 | self.save()
40 | self.fill(1)
41 | self.rect(0, 0, width, height)
42 | self.restore()
43 |
44 | def _writeDataToFile(self, data, path, options):
45 | frameRate = round(1.0 / self._frameDurations[0], 3)
46 | frameDurations = set(self._frameDurations)
47 | if len(frameDurations) > 1:
48 | warnings.warn("Exporting to mp4 doesn't support varying frame durations, only the first value was used.")
49 | options["multipage"] = True
50 | codec = options.get("ffmpegCodec", "libx264")
51 | tempDir = tempfile.mkdtemp(suffix=".mp4tmp")
52 | try:
53 | super(MP4Context, self)._writeDataToFile(data, os.path.join(tempDir, "frame.png"), options)
54 | generateMP4(os.path.join(tempDir, "frame_%d.png"), path, frameRate, codec)
55 | finally:
56 | shutil.rmtree(tempDir)
57 |
--------------------------------------------------------------------------------
/drawBot/context/printContext.py:
--------------------------------------------------------------------------------
1 | import AppKit # type: ignore
2 | from fontTools.pens.basePen import AbstractPen
3 |
4 | from .baseContext import BaseContext
5 |
6 |
7 | class StringPen(AbstractPen):
8 | def __init__(self, seperator=None):
9 | self.data = []
10 | if seperator is None:
11 | seperator = " "
12 | self.seperator = seperator
13 |
14 | def moveTo(self, pt):
15 | x, y = pt
16 | self.data.append("moveTo %s %s" % (x, y))
17 |
18 | def lineTo(self, pt):
19 | x, y = pt
20 | self.data.append("lineTo %s %s" % (x, y))
21 |
22 | def curveTo(self, *pts):
23 | self.data.append("curveTo %s" % " ".join(["%s %s" % (x, y) for x, y in pts]))
24 |
25 | def qCurveTo(self, *pts):
26 | self.data.append("qCurveTo %s" % " ".join(["%s %s" % (x, y) for x, y in pts]))
27 |
28 | def closePath(self):
29 | self.data.append("closePath")
30 |
31 | def endPath(self):
32 | self.data.append("endPath")
33 |
34 | def __repr__(self):
35 | return self.seperator.join(self.data)
36 |
37 |
38 | class PrintContext(BaseContext):
39 | fileExtensions = ["*"]
40 | validateSaveImageOptions = False
41 |
42 | def _newPage(self, width, height):
43 | print("newPage %s %s" % (width, height))
44 |
45 | def _save(self):
46 | print("save")
47 |
48 | def _restore(self):
49 | print("restore")
50 |
51 | def _blendMode(self, operation):
52 | print("blendMode %s" % operation)
53 |
54 | def _opacity(self, value):
55 | print("opacity %s" % value)
56 |
57 | def _drawPath(self):
58 | pen = StringPen()
59 | self._state.path.drawToPen(pen)
60 | print("drawPath %s" % pen)
61 |
62 | def _clipPath(self):
63 | pen = StringPen()
64 | self._state.path.drawToPen(pen)
65 | print("clipPath %s" % pen)
66 |
67 | def _transform(self, matrix):
68 | print("transform %s" % " ".join(["%s" % i for i in matrix]))
69 |
70 | def _textBox(self, txt, xywh, align):
71 | # XXX
72 | # should a formatted string be printed in parts???
73 | x, y, w, h = xywh
74 | print("textBox %s %r %r %r %r %s" % (txt, x, y, w, h, align))
75 |
76 | def _image(self, path, xy, alpha, pageNumber):
77 | x, y = xy
78 | if isinstance(path, AppKit.NSImage):
79 | path = "Image Object"
80 | print("image %s %s %s %s %s" % (path, x, y, alpha, pageNumber))
81 |
82 | def _frameDuration(self, seconds):
83 | print("frameDuration %s" % seconds)
84 |
85 | def _reset(self, other=None):
86 | print("reset %s" % other)
87 |
88 | def _saveImage(self, path, options):
89 | print("saveImage %s %s" % (path, options))
90 |
91 | def _printImage(self, pdf=None):
92 | print("printImage %s" % pdf)
93 |
94 | def _linkURL(self, url, xywh):
95 | x, y, w, h = xywh
96 | print("linkURL %s %s %s %s %s" % (url, x, y, w, h))
97 |
98 | def _linkDestination(self, name, xy):
99 | x, y = xy
100 | print("linkDestination %s %s %s" % (name, x, y))
101 |
102 | def _linkRect(self, name, xywh):
103 | x, y, w, h = xywh
104 | print("linkRect %s %s %s %s %s" % (name, x, y, w, h))
105 |
--------------------------------------------------------------------------------
/drawBot/context/tools/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/drawBot/context/tools/__init__.py
--------------------------------------------------------------------------------
/drawBot/context/tools/drawBotbuiltins.py:
--------------------------------------------------------------------------------
1 | def norm(value: float, start: float, stop: float) -> float:
2 | """
3 | Return the interpolation factor (between 0 and 1) of a `value` between `start` and `stop`.
4 | """
5 | return (value - start) / (stop - start)
6 |
7 |
8 | def lerp(start: float, stop: float, factor: float) -> float:
9 | """
10 | Return an interpolated value between `start` and `stop` using interpolation factor `factor`.
11 | """
12 | return start + (stop - start) * factor
13 |
14 |
15 | def remap(value: float, start1: float, stop1: float, start2: float, stop2: float, clamp: bool = False) -> float:
16 | """
17 | Re-maps a number from one range to another.
18 | """
19 | factor = norm(value, start1, stop1)
20 | if clamp:
21 | if factor < 0:
22 | factor = 0
23 | elif factor > 1:
24 | factor = 1
25 | return lerp(start2, stop2, factor)
26 |
--------------------------------------------------------------------------------
/drawBot/context/tools/gifTools.py:
--------------------------------------------------------------------------------
1 | import os
2 | import shutil
3 | import tempfile
4 |
5 | import AppKit # type: ignore
6 |
7 | from drawBot.misc import executeExternalProcess, getExternalToolPath
8 |
9 |
10 | def generateGif(sourcePaths, destPath, delays, loop=True):
11 | gifsiclePath = getExternalToolPath(os.path.dirname(__file__), "gifsicle")
12 | assert gifsiclePath is not None
13 | cmds = [
14 | # gifsicle path
15 | gifsiclePath,
16 | # optimize level
17 | # "-O3",
18 | # ignore warnings
19 | "-w",
20 | # force to 256 colors
21 | "--colors",
22 | "256",
23 | ]
24 | if loop:
25 | # make it loop
26 | cmds.append("--loop")
27 | # add source paths with delay for each frame
28 | for i, inputPath in enumerate(sourcePaths):
29 | cmds += [
30 | # add the frame duration
31 | "--delay",
32 | "%i" % delays[i],
33 | # add the input gif for each frame
34 | inputPath,
35 | ]
36 |
37 | cmds += [
38 | # output path
39 | "--output",
40 | destPath,
41 | ]
42 | executeExternalProcess(cmds)
43 | # remove the temp input gifs
44 | for inputPath in sourcePaths:
45 | os.remove(inputPath)
46 |
47 |
48 | _explodedGifCache = {}
49 |
50 |
51 | def _explodeGif(path):
52 | gifsiclePath = getExternalToolPath(os.path.dirname(__file__), "gifsicle")
53 | if isinstance(path, AppKit.NSURL):
54 | path = path.path()
55 | destRoot = tempfile.mkdtemp()
56 | cmds = [
57 | gifsiclePath,
58 | # explode
59 | "--explode",
60 | # source path
61 | path,
62 | ]
63 | executeExternalProcess(cmds, cwd=destRoot)
64 | files = os.listdir(destRoot)
65 | _explodedGifCache[path] = dict(
66 | source=destRoot,
67 | fileNames=sorted(files),
68 | )
69 |
70 |
71 | def clearExplodedGifCache():
72 | for path, info in _explodedGifCache.items():
73 | shutil.rmtree(info["source"])
74 | _explodedGifCache.clear()
75 |
76 |
77 | def gifFrameCount(path):
78 | if isinstance(path, AppKit.NSURL):
79 | path = path.path()
80 | if path not in _explodedGifCache:
81 | _explodeGif(path)
82 | frameCount = len(_explodedGifCache[path]["fileNames"])
83 | if frameCount == 0:
84 | return None
85 | return frameCount
86 |
87 |
88 | def gifFrameAtIndex(path, index):
89 | if isinstance(path, AppKit.NSURL):
90 | path = path.path()
91 | if path not in _explodedGifCache:
92 | _explodeGif(path)
93 | source = _explodedGifCache[path]["source"]
94 | fileNames = _explodedGifCache[path]["fileNames"]
95 | fileName = os.path.join(source, fileNames[index])
96 | url = AppKit.NSURL.fileURLWithPath_(fileName)
97 | return AppKit.NSImage.alloc().initByReferencingURL_(url)
98 |
--------------------------------------------------------------------------------
/drawBot/context/tools/gifsicleLicense:
--------------------------------------------------------------------------------
1 | Copyright/License
2 |
3 | All source code is Copyright (C) 1997-2013 Eddie Kohler.
4 |
5 | IF YOU PLAN TO USE GIFSICLE ONLY TO CREATE OR MODIFY GIF IMAGES, DON'T WORRY ABOUT THE REST OF THIS SECTION. Anyone can use Gifsicle however they wish; the license applies only to those who plan to copy, distribute, or alter its code. If you use Gifsicle for an organizational or commercial Web site, I would appreciate a link to the Gifsicle home page on any 'About This Server' page, but it's not required.
6 |
7 | This code is distributed under the GNU General Public License, Version 2 (and only Version 2). The GNU General Public License is available via the Web at http://www.gnu.org/licenses/gpl.html or in the 'COPYING' file in this directory.
8 |
9 | The following alternative license may be used at your discretion.
10 |
11 | Permission is granted to copy, distribute, or alter Gifsicle, whole or in part, as long as source code copyright notices are kept intact, with the following restriction: Developers or distributors who plan to use Gifsicle code, whole or in part, in a product whose source code will not be made available to the end user -- more precisely, in a context which would violate the GPL -- MUST contact the author and obtain permission before doing so.
--------------------------------------------------------------------------------
/drawBot/context/tools/mp4Tools.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from drawBot.misc import executeExternalProcess, getExternalToolPath
4 |
5 |
6 | def generateMP4(imageTemplate, mp4path, frameRate, codec="libx264"):
7 | ffmpegPath = getExternalToolPath(os.path.dirname(__file__), "ffmpeg")
8 | assert ffmpegPath is not None
9 | cmds = [
10 | # ffmpeg path
11 | ffmpegPath,
12 | "-y", # overwrite existing files
13 | "-loglevel",
14 | "16", # 'error, 16' Show all errors, including ones which can be recovered from.
15 | "-r",
16 | str(frameRate), # frame rate
17 | "-i",
18 | imageTemplate, # input sequence
19 | "-c:v",
20 | codec, # codec
21 | "-crf",
22 | "20", # Constant Rate Factor
23 | "-pix_fmt",
24 | "yuv420p", # pixel format
25 | mp4path, # output path
26 | ]
27 | executeExternalProcess(cmds)
28 |
--------------------------------------------------------------------------------
/drawBot/drawBotPageDrawingTools.py:
--------------------------------------------------------------------------------
1 | from .drawBotDrawingTools import _drawBotDrawingTool, DrawBotDrawingTool
2 |
3 |
4 | class DummyDrawBotDrawingTool(DrawBotDrawingTool):
5 | def __init__(self, instructionSet):
6 | super(DummyDrawBotDrawingTool, self).__init__()
7 | # add the instruction set
8 | self._instructionsStack.append(instructionSet)
9 | # draw all instructions into it self
10 | # just to set all attributes into the dummycontext
11 | # this is important for the current state
12 | self._drawInContext(self)
13 |
14 | def _addInstruction(self, callback, *args, **kwargs):
15 | # dont add any instructions
16 | pass
17 |
18 |
19 | class DrawBotPage:
20 | def __init__(self, instructionSet):
21 | self._instructionSet = instructionSet
22 |
23 | def __enter__(self):
24 | # copy/save a state of the existing drawing tool
25 | self._originalTool = _drawBotDrawingTool._copy()
26 | # load the instructions
27 | pageTool = DummyDrawBotDrawingTool(self._instructionSet)
28 | # overwrite the globals newPage and size
29 | _drawBotDrawingTool._isSinglePage = True
30 | # reset the existing one, with the page tool
31 | _drawBotDrawingTool._reset(pageTool)
32 | return self
33 |
34 | def __exit__(self, type, value, traceback):
35 | # reset the main drawing tool with a saved state of the tool
36 | _drawBotDrawingTool._reset(self._originalTool)
37 | # reset the globals newPage and size
38 | _drawBotDrawingTool._isSinglePage = False
39 |
--------------------------------------------------------------------------------
/drawBot/drawBotSettings.py:
--------------------------------------------------------------------------------
1 | __version__ = "3.132"
2 |
--------------------------------------------------------------------------------
/drawBot/macOSVersion.py:
--------------------------------------------------------------------------------
1 | from packaging.version import Version
2 | import platform
3 |
4 | macOSVersion = Version(platform.mac_ver("0.0.0")[0])
5 |
--------------------------------------------------------------------------------
/drawBot/ui/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/drawBot/ui/__init__.py
--------------------------------------------------------------------------------
/drawBot/ui/debug.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | from AppKit import NSPanel # type: ignore
4 | from Foundation import NSLog # type: ignore
5 | from vanilla import FloatingWindow
6 |
7 | from .codeEditor import OutPutEditor
8 |
9 |
10 | class ShowHideNSPanel(NSPanel):
11 | def close(self):
12 | self.orderOut_(None)
13 |
14 |
15 | class ShowHideFloatingWindow(FloatingWindow):
16 | nsWindowClass = ShowHideNSPanel
17 |
18 |
19 | class DebugWindowController:
20 | """
21 | Debugger catching all sys.stdout and sys.sterr outside a script.
22 | """
23 |
24 | def __init__(self):
25 | self.w = ShowHideFloatingWindow(
26 | (300, 500), "Debugger", minSize=(200, 300), autosaveName="DrawBotDebugWindow", initiallyVisible=False
27 | )
28 |
29 | self.w.debugText = OutPutEditor((0, 0, -0, -0), readOnly=True)
30 |
31 | self._savedStdout = sys.stdout
32 | self._savedStderr = sys.stderr
33 |
34 | sys.stdout = self
35 | sys.stderr = self
36 |
37 | self.w.open()
38 |
39 | def showHide(self):
40 | if self.w.isVisible():
41 | self.w.hide()
42 | else:
43 | self.show()
44 |
45 | def show(self):
46 | self.w.show()
47 | self.w.select()
48 |
49 | def clear(self, sender=None):
50 | """
51 | Clear all text in the output window.
52 | """
53 | self.w.debugText.clear()
54 |
55 | def write(self, inputText):
56 | """
57 | Write text in the output window.
58 | Duplicate the text also in the default logging system
59 | so it will appear in the console.app.
60 | """
61 | NSLog(inputText)
62 | self.w.debugText.append(inputText)
63 | self.w.debugText.scrollToEnd()
64 |
65 | def flush(self):
66 | pass
67 |
--------------------------------------------------------------------------------
/drawBot/ui/drawBotPackageController.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | from defconAppKit.windows.baseWindow import BaseWindowController
4 |
5 | import vanilla
6 |
7 | from drawBot.drawBotPackage import DrawBotPackage
8 |
9 |
10 | class DrawBotPackageController(BaseWindowController):
11 | packageInfo = [
12 | "name",
13 | "version",
14 | "developer",
15 | "developerURL",
16 | "requiresVersion",
17 | "mainScript",
18 | ]
19 |
20 | def __init__(self):
21 | self.bundle = DrawBotPackage()
22 |
23 | self.w = vanilla.Window((350, 320), "Package builder")
24 |
25 | y = 10
26 | m = 120
27 | for attr in self.packageInfo:
28 | text = vanilla.TextBox((10, y, m - 15, 22), "%s:" % attr, alignment="right")
29 | edit = vanilla.EditText((m, y, -10, 22), placeholder=getattr(self.bundle.info, attr))
30 |
31 | setattr(self.w, "%s_text" % attr, text)
32 | setattr(self.w, "%s_edit" % attr, edit)
33 | y += 30
34 |
35 | self.w.note = vanilla.TextBox((m, y, -10, 22), "Everything is optional.", sizeStyle="mini")
36 | y += 30
37 | self.w.h1 = vanilla.HorizontalLine((0, y, 0, 1))
38 | y += 10
39 | self.w.scriptRoot_text = vanilla.TextBox((10, y, m - 15, 22), "Script Root:", alignment="right")
40 | self.w.scriptRoot = vanilla.PathControl(
41 | (m, y - 2, -10, 22), None, pathStyle="popUp", callback=self.scriptRootCallback
42 | )
43 | y += 25
44 | self.w.scriptRoot_note = vanilla.TextBox(
45 | (m, y, -10, 22), "A folder containing all required python files.", sizeStyle="mini"
46 | )
47 |
48 | self.w.buildButton = vanilla.Button((-120, -30, -10, 22), "Build", callback=self.buildCallback)
49 | self.w.open()
50 |
51 | def scriptRootCallback(self, sender):
52 | url = sender.get()
53 | if url and not os.path.isdir(url):
54 | sender.set(None)
55 | self.showMessage("Package error.", "The script root must be a folder.")
56 |
57 | def buildCallback(self, sender):
58 | for attr in self.packageInfo:
59 | control = getattr(self.w, "%s_edit" % attr)
60 | value = str(control.get())
61 | if value:
62 | setattr(self.bundle.info, attr, value)
63 | root = self.w.scriptRoot.get()
64 | if root is None:
65 | self.showMessage("Package error.", "A scripting root must be provided.")
66 | return
67 |
68 | def saveBundle(path):
69 | if path:
70 | succes, report = self.bundle.buildPackage(path, root)
71 | if not succes:
72 | self.showMessage("Package error.", report)
73 |
74 | self.showPutFile(["drawbot"], saveBundle)
75 |
--------------------------------------------------------------------------------
/examples/roundedRect.py:
--------------------------------------------------------------------------------
1 | import drawBot as db
2 |
3 |
4 | def roundedRect(
5 | x: float,
6 | y: float,
7 | w: float,
8 | h: float,
9 | radius: float,
10 | radiusBottomRight: float | None = None,
11 | radiusTopRight: float | None = None,
12 | radiusTopLeft: float | None = None,
13 | ):
14 | """
15 | Draw a rounded rect from position `x`, `y` with given width and height and given `radius`.
16 |
17 | A radiuses that exceeds the width or height of the rectangle will be clipped.
18 |
19 | Optionally a radius could be provided for each corner the following order:
20 | bottom left, bottom right, top right, top left
21 |
22 | .. downloadcode:: roundedRect.py
23 |
24 | # draw a rounding rect
25 | # x y w h radius
26 | roundedRect(100, 100, 200, 200, 10)
27 |
28 | # x y w h bl br tr tl
29 | roundedRect(100, 330, 200, 200, 10, 30, 40, 50)
30 | """
31 | # do some checking on the radiuses
32 | radiusBottomLeft = radius
33 | if radiusTopLeft is None and radiusTopRight is None and radiusBottomRight is None:
34 | radiusTopLeft = radiusTopRight = radiusBottomRight = radius
35 |
36 | assert radius and radiusBottomRight and radiusTopRight and radiusTopLeft
37 | if radiusBottomLeft + radiusBottomRight > w:
38 | diff = (radiusBottomLeft + radiusBottomRight - w) * 0.5
39 | radiusBottomLeft -= diff
40 | radiusBottomRight -= diff
41 | if radiusTopLeft + radiusTopRight > w:
42 | diff = (radiusTopLeft + radiusTopRight - w) * 0.5
43 | radiusTopLeft -= diff
44 | radiusTopRight -= diff
45 | if radiusBottomLeft + radiusTopLeft > h:
46 | diff = (radiusBottomLeft + radiusTopLeft - h) * 0.5
47 | radiusBottomLeft -= diff
48 | radiusTopLeft -= diff
49 | if radiusBottomRight + radiusTopRight > h:
50 | diff = (radiusBottomRight + radiusTopRight - h) * 0.5
51 | radiusBottomRight -= diff
52 | radiusTopRight -= diff
53 |
54 | minValue = min(w, h)
55 |
56 | if radiusBottomRight < 0:
57 | radiusBottomRight = 0
58 | if radiusTopRight < 0:
59 | radiusTopRight = 0
60 | if radiusBottomLeft < 0:
61 | radiusBottomLeft = 0
62 | if radiusTopLeft < 0:
63 | radiusTopLeft = 0
64 |
65 | if radiusBottomRight > minValue:
66 | radiusBottomRight = minValue
67 | if radiusTopRight > minValue:
68 | radiusTopRight = minValue
69 | if radiusBottomLeft > minValue:
70 | radiusBottomLeft = minValue
71 | if radiusTopLeft > minValue:
72 | radiusTopLeft = minValue
73 |
74 | # start drawing
75 | path = db.BezierPath()
76 | path.moveTo((x + radiusBottomLeft, y))
77 | path.lineTo((x + w - radiusBottomRight, y))
78 | path.arcTo((x + w, y), (x + w, y + radiusBottomRight), radiusBottomRight)
79 | path.lineTo((x + w, y + h - radiusTopRight))
80 | path.arcTo((x + w, y + h), (x + w - radiusTopRight, y + h), radiusTopRight)
81 | path.lineTo((x + radiusTopLeft, y + h))
82 | path.arcTo((x, y + h), (x, y + h - radiusTopLeft), radiusTopLeft)
83 | path.lineTo((x, y + radiusBottomLeft))
84 | path.arcTo((x, y), (x + radiusBottomLeft, y), radiusBottomLeft)
85 | path.closePath()
86 | db.drawPath(path)
87 |
88 |
89 | if __name__ == "__main__":
90 | # draw a rounded rect
91 | roundedRect(10, 10, 100, 100, 20, 20, 70, 90)
92 |
--------------------------------------------------------------------------------
/examples/star.py:
--------------------------------------------------------------------------------
1 | from math import cos, pi, sin
2 |
3 | import drawBot as db
4 |
5 |
6 | def star(center, points, inner, outer):
7 | # create a new path
8 | db.newPath()
9 | # move the pen to the initial position
10 | X, Y = center
11 | db.moveTo((X, Y + outer))
12 | for i in range(1, int(2 * points)):
13 | angle = i * pi / points
14 | x = sin(angle)
15 | y = cos(angle)
16 | if i % 2:
17 | radius = inner
18 | else:
19 | radius = outer
20 | x = X + radius * x
21 | y = Y + radius * y
22 | db.lineTo((x, y))
23 | db.closePath()
24 | db.drawPath()
25 |
26 |
27 | if __name__ == "__main__":
28 | star((312, 344), 5, 60, 110)
29 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 | The BSD License
2 |
3 | Copyright (c) 2003-2019 Just van Rossum, Erik van Blokland, Frederik Berlaen
4 |
5 | All rights reserved.
6 |
7 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
8 |
9 | Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
10 | 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.
11 | 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.
12 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # https://stackoverflow.com/questions/78859635/py2app-error-17-file-exists-when-running-py2app-for-the-first-time
2 | setuptools==70.3.0
3 | packaging
4 | pyobjc
5 | corefoundationasyncio
6 | py2app
7 | cocoa-vanilla==0.5.0
8 | defcon
9 | git+https://github.com/robotools/defconAppKit
10 | fontTools[ufo,lxml,woff,unicode,type1]
11 | fs
12 | brotli
13 | pygments
14 | jedi
15 | pillow==10.1.0 # 10.2.0 has an incompatibility with older x86 macOS: https://github.com/python-pillow/Pillow/issues/6862#issuecomment-1913552472
16 | attrs
17 | booleanOperations
18 | mutatorMath
19 | git+https://github.com/robotools/fontParts
20 | fontMath
21 | git+https://github.com/robotools/fontPens
22 | git+https://github.com/typesupply/woffTools
23 | git+https://github.com/robotools/compositor
24 | git+https://github.com/robotools/extractor
25 | git+https://github.com/typesupply/ufo2svg
26 | git+https://github.com/robotools/ufo2fdk
27 | git+https://github.com/typesupply/feaPyFoFum
28 | git+https://github.com/typesupply/feaTools2
29 | pip
30 | packaging
31 | ruff-api
32 | pytz
33 | delocate==0.10.7 # for merging intel+silicon wheels into universal2
34 |
--------------------------------------------------------------------------------
/ruff.toml:
--------------------------------------------------------------------------------
1 | line-length = 120
2 | target-version = "py311"
3 |
--------------------------------------------------------------------------------
/scripting/generateDrawbotInit.py:
--------------------------------------------------------------------------------
1 | """
2 | We need to "physically" write the names of the functions/methods that are exposed
3 | with the drawBot module to allow static analysis by tools like mypy or pyright
4 | to leverage the hints we have in the interfaces
5 |
6 | """
7 |
8 | from pathlib import Path
9 |
10 | import ruff_api
11 |
12 | from drawBot import _drawBotDrawingTool
13 | from drawBot.context.tools import drawBotbuiltins
14 | from drawBot.misc import ruff_options
15 |
16 | INIT_PATH = Path(__file__).parent.parent / "drawBot/__init__.py"
17 |
18 |
19 | def generateInitCode():
20 | code = []
21 | for name in _drawBotDrawingTool.__all__:
22 | if name.startswith("_"):
23 | continue
24 | code.append(f"{name} = _drawBotDrawingTool.{name}")
25 |
26 | code.append("")
27 | code.append("# directly import FormattedString, BezierPath, and ImageObject as classes")
28 | code.append("from drawBot.context.baseContext import FormattedString, BezierPath")
29 | code.append("from drawBot.context.tools.imageObject import ImageObject")
30 |
31 | code.append("")
32 | code.append("from drawBot.context.tools import drawBotbuiltins")
33 | for name in dir(drawBotbuiltins):
34 | if name.startswith("_"):
35 | continue
36 | code.append(f"{name} = drawBotbuiltins.{name}")
37 |
38 | initText = INIT_PATH.read_text()
39 | before = []
40 | for eachLine in initText.splitlines():
41 | before.append(eachLine)
42 | if eachLine == "# --- section automatically generated --- #":
43 | break
44 |
45 | return ruff_api.format_string("__init__.py", "\n".join(before) + "\n" + "\n".join(code), ruff_options())
46 |
47 |
48 | if __name__ == "__main__":
49 | initCode = generateInitCode()
50 | INIT_PATH.write_text(initCode)
51 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | from __future__ import absolute_import, division, print_function
3 |
4 | import os
5 | import re
6 | import shutil
7 |
8 | from setuptools import setup
9 |
10 | _versionRE = re.compile(r"__version__\s*=\s*\"([^\"]+)\"")
11 | # read the version number for the settings file
12 | with open("drawBot/drawBotSettings.py", "r") as settings:
13 | code = settings.read()
14 | found = _versionRE.search(code)
15 | assert found is not None, "drawBot __version__ not found"
16 | __version__ = found.group(1)
17 |
18 |
19 | externalTools = ("ffmpeg", "gifsicle", "mkbitmap", "potrace")
20 | externalToolsSourceRoot = os.path.join(os.path.dirname(__file__), "Resources", "externalTools")
21 | externalToolsDestRoot = os.path.join(os.path.dirname(__file__), "drawBot", "context", "tools")
22 |
23 | # copy all external tools into drawBot.context.tools folder
24 | for externalTool in externalTools:
25 | source = os.path.join(externalToolsSourceRoot, externalTool)
26 | dest = os.path.join(externalToolsDestRoot, externalTool)
27 | shutil.copyfile(source, dest)
28 | os.chmod(dest, 0o775)
29 |
30 |
31 | setup(
32 | name="drawBot",
33 | version=__version__,
34 | description="DrawBot is a powerful tool that invites you to write simple Python scripts to generate two-dimensional graphics. The builtin graphics primitives support rectangles, ovals, (bezier) paths, polygons, text objects and transparency.",
35 | author="Just van Rossum, Erik van Blokland, Frederik Berlaen",
36 | author_email="frederik@typemytype.com",
37 | url="http://drawbot.com",
38 | license="BSD",
39 | python_requires=">=3.11",
40 | packages=["drawBot", "drawBot.context", "drawBot.context.tools", "drawBot.ui"],
41 | package_data={
42 | "drawBot": ["context/tools/ffmpeg", "context/tools/gifsicle", "context/tools/mkbitmap", "context/tools/potrace"]
43 | },
44 | install_requires=[
45 | "pyobjc",
46 | "fontTools",
47 | "booleanOperations",
48 | "pillow",
49 | "packaging",
50 | ],
51 | include_package_data=True,
52 | )
53 |
54 | # remove all external tools
55 | for externalTool in externalTools:
56 | dest = os.path.join(externalToolsDestRoot, externalTool)
57 | os.remove(dest)
58 |
--------------------------------------------------------------------------------
/test-requirements.txt:
--------------------------------------------------------------------------------
1 | pillow
2 | attrs
3 | packaging
4 | mypy
5 | ruff
6 | ruff-api
7 |
--------------------------------------------------------------------------------
/tests/data/MutatorSans.ttc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/MutatorSans.ttc
--------------------------------------------------------------------------------
/tests/data/MutatorSans.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/MutatorSans.ttf
--------------------------------------------------------------------------------
/tests/data/drawBot.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/drawBot.bmp
--------------------------------------------------------------------------------
/tests/data/drawBot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/drawBot.jpg
--------------------------------------------------------------------------------
/tests/data/drawBot.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/drawBot.pdf
--------------------------------------------------------------------------------
/tests/data/drawBot.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/drawBot.png
--------------------------------------------------------------------------------
/tests/data/drawBot144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/drawBot144.png
--------------------------------------------------------------------------------
/tests/data/example_appendGlyphFormattedString.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_appendGlyphFormattedString.png
--------------------------------------------------------------------------------
/tests/data/example_bezierPath.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_bezierPath.png
--------------------------------------------------------------------------------
/tests/data/example_blendMode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_blendMode.png
--------------------------------------------------------------------------------
/tests/data/example_clipPath.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_clipPath.png
--------------------------------------------------------------------------------
/tests/data/example_cmykFill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_cmykFill.png
--------------------------------------------------------------------------------
/tests/data/example_cmykLinearGradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_cmykLinearGradient.png
--------------------------------------------------------------------------------
/tests/data/example_cmykRadialGradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_cmykRadialGradient.png
--------------------------------------------------------------------------------
/tests/data/example_cmykShadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_cmykShadow.png
--------------------------------------------------------------------------------
/tests/data/example_cmykStroke.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_cmykStroke.png
--------------------------------------------------------------------------------
/tests/data/example_colorSpace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_colorSpace.png
--------------------------------------------------------------------------------
/tests/data/example_drawPath.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_drawPath.png
--------------------------------------------------------------------------------
/tests/data/example_fill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_fill.png
--------------------------------------------------------------------------------
/tests/data/example_fontNamedInstance.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_fontNamedInstance.png
--------------------------------------------------------------------------------
/tests/data/example_fontVariations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_fontVariations.png
--------------------------------------------------------------------------------
/tests/data/example_formattedString.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_formattedString.png
--------------------------------------------------------------------------------
/tests/data/example_frameDuration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_frameDuration.png
--------------------------------------------------------------------------------
/tests/data/example_hyphenation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_hyphenation.png
--------------------------------------------------------------------------------
/tests/data/example_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_image.png
--------------------------------------------------------------------------------
/tests/data/example_imageObject.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_imageObject.png
--------------------------------------------------------------------------------
/tests/data/example_indent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_indent.png
--------------------------------------------------------------------------------
/tests/data/example_installFont.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_installFont.png
--------------------------------------------------------------------------------
/tests/data/example_language.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_language.png
--------------------------------------------------------------------------------
/tests/data/example_line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_line.png
--------------------------------------------------------------------------------
/tests/data/example_lineCap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_lineCap.png
--------------------------------------------------------------------------------
/tests/data/example_lineDash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_lineDash.png
--------------------------------------------------------------------------------
/tests/data/example_lineHeight.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_lineHeight.png
--------------------------------------------------------------------------------
/tests/data/example_lineJoin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_lineJoin.png
--------------------------------------------------------------------------------
/tests/data/example_linearGradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_linearGradient.png
--------------------------------------------------------------------------------
/tests/data/example_miterLimit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_miterLimit.png
--------------------------------------------------------------------------------
/tests/data/example_newDrawing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_newDrawing.png
--------------------------------------------------------------------------------
/tests/data/example_newPage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_newPage.png
--------------------------------------------------------------------------------
/tests/data/example_opacity.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_opacity.png
--------------------------------------------------------------------------------
/tests/data/example_openTypeFeatures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_openTypeFeatures.png
--------------------------------------------------------------------------------
/tests/data/example_openTypeFeaturesFormattedString.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_openTypeFeaturesFormattedString.png
--------------------------------------------------------------------------------
/tests/data/example_oval.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_oval.png
--------------------------------------------------------------------------------
/tests/data/example_overflowText.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_overflowText.png
--------------------------------------------------------------------------------
/tests/data/example_pages.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_pages.png
--------------------------------------------------------------------------------
/tests/data/example_pixelColor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_pixelColor.png
--------------------------------------------------------------------------------
/tests/data/example_polygon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_polygon.png
--------------------------------------------------------------------------------
/tests/data/example_printImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_printImage.png
--------------------------------------------------------------------------------
/tests/data/example_radialGradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_radialGradient.png
--------------------------------------------------------------------------------
/tests/data/example_rect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_rect.png
--------------------------------------------------------------------------------
/tests/data/example_saveImage.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_saveImage.png
--------------------------------------------------------------------------------
/tests/data/example_saveImageResolutionExample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_saveImageResolutionExample.png
--------------------------------------------------------------------------------
/tests/data/example_savedState.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_savedState.png
--------------------------------------------------------------------------------
/tests/data/example_shadow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_shadow.png
--------------------------------------------------------------------------------
/tests/data/example_size.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_size.png
--------------------------------------------------------------------------------
/tests/data/example_strikethrough.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_strikethrough.png
--------------------------------------------------------------------------------
/tests/data/example_stroke.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_stroke.png
--------------------------------------------------------------------------------
/tests/data/example_strokeWidth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_strokeWidth.png
--------------------------------------------------------------------------------
/tests/data/example_tabs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_tabs.png
--------------------------------------------------------------------------------
/tests/data/example_tabsFormattedString.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_tabsFormattedString.png
--------------------------------------------------------------------------------
/tests/data/example_text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_text.png
--------------------------------------------------------------------------------
/tests/data/example_textBox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_textBox.png
--------------------------------------------------------------------------------
/tests/data/example_textBoxInPath.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_textBoxInPath.png
--------------------------------------------------------------------------------
/tests/data/example_textRTL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_textRTL.png
--------------------------------------------------------------------------------
/tests/data/example_tracking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_tracking.png
--------------------------------------------------------------------------------
/tests/data/example_underline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_underline.png
--------------------------------------------------------------------------------
/tests/data/example_url.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_url.png
--------------------------------------------------------------------------------
/tests/data/example_variablesUI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/example_variablesUI.png
--------------------------------------------------------------------------------
/tests/data/expected_appendGlyphWithFontVariations.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_appendGlyphWithFontVariations.pdf
--------------------------------------------------------------------------------
/tests/data/expected_appendGlyphWithFontVariations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_appendGlyphWithFontVariations.png
--------------------------------------------------------------------------------
/tests/data/expected_appendGlyphWithFontVariations.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | &
6 |
7 |
8 | �
9 |
10 |
11 | �
12 |
13 |
14 | &
15 |
16 |
17 |
--------------------------------------------------------------------------------
/tests/data/expected_appendGlyphWithTracking.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_appendGlyphWithTracking.pdf
--------------------------------------------------------------------------------
/tests/data/expected_appendGlyphWithTracking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_appendGlyphWithTracking.png
--------------------------------------------------------------------------------
/tests/data/expected_appendGlyphWithTracking.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | �
6 |
7 |
8 | �
9 |
10 |
11 |
12 |
13 | �
14 |
15 |
16 | �
17 |
18 |
19 |
--------------------------------------------------------------------------------
/tests/data/expected_booleanOperations.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_booleanOperations.pdf
--------------------------------------------------------------------------------
/tests/data/expected_booleanOperations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_booleanOperations.png
--------------------------------------------------------------------------------
/tests/data/expected_booleanOperations.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/tests/data/expected_booleanOperations2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_booleanOperations2.pdf
--------------------------------------------------------------------------------
/tests/data/expected_booleanOperations2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_booleanOperations2.png
--------------------------------------------------------------------------------
/tests/data/expected_booleanOperations2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/tests/data/expected_centeredTransform.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_centeredTransform.pdf
--------------------------------------------------------------------------------
/tests/data/expected_centeredTransform.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_centeredTransform.png
--------------------------------------------------------------------------------
/tests/data/expected_centeredTransform.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/tests/data/expected_centeredTransformBezierPath.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_centeredTransformBezierPath.pdf
--------------------------------------------------------------------------------
/tests/data/expected_centeredTransformBezierPath.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_centeredTransformBezierPath.png
--------------------------------------------------------------------------------
/tests/data/expected_centeredTransformBezierPath.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/tests/data/expected_cmykFill.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_cmykFill.pdf
--------------------------------------------------------------------------------
/tests/data/expected_cmykFill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_cmykFill.png
--------------------------------------------------------------------------------
/tests/data/expected_cmykLinearGradient.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_cmykLinearGradient.pdf
--------------------------------------------------------------------------------
/tests/data/expected_cmykLinearGradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_cmykLinearGradient.png
--------------------------------------------------------------------------------
/tests/data/expected_cmykLinearGradient.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/tests/data/expected_cmykRadialGradient.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_cmykRadialGradient.pdf
--------------------------------------------------------------------------------
/tests/data/expected_cmykRadialGradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_cmykRadialGradient.png
--------------------------------------------------------------------------------
/tests/data/expected_cmykRadialGradient.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/tests/data/expected_dashStroke.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_dashStroke.pdf
--------------------------------------------------------------------------------
/tests/data/expected_dashStroke.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_dashStroke.png
--------------------------------------------------------------------------------
/tests/data/expected_dashStroke.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/tests/data/expected_fill.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_fill.pdf
--------------------------------------------------------------------------------
/tests/data/expected_fill.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_fill.png
--------------------------------------------------------------------------------
/tests/data/expected_fontAttributes.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_fontAttributes.pdf
--------------------------------------------------------------------------------
/tests/data/expected_fontAttributes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_fontAttributes.png
--------------------------------------------------------------------------------
/tests/data/expected_fontAttributes.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/tests/data/expected_fontAttributes.txt:
--------------------------------------------------------------------------------
1 | Times
2 | Times-Roman
3 | True
4 | True
5 | False
6 | True
7 | True
8 | False
9 | Times.ttc
10 | ['.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', 'numbersign']
11 | 37.5
12 | -12.5
13 | 22.6806640625
14 | 33.0810546875
15 | 0.0
16 | 61.0
17 |
18 | ../data/MutatorSans.ttf
19 | MutatorMathTest-LightCondensed
20 | True
21 | False
22 | False
23 | True
24 | False
25 | False
26 | MutatorSans.ttf
27 | ['A', 'B', 'C', 'D', 'E', 'F']
28 | 40.000152587890625
29 | -9.999847412109375
30 | 25.0
31 | 35.0
32 | 9.999847412109375
33 | 60.0
34 |
35 | AppleColorEmoji
36 | True
37 |
38 | MutatorMathTest-LightCondensed
39 | MutatorSans.ttc 0
40 | MutatorMathTest-LightWide
41 | MutatorSans.ttc 1
42 | MutatorMathTest-BoldCondensed
43 | MutatorSans.ttc 2
44 | MutatorMathTest-BoldWide
45 | MutatorSans.ttc 3
46 |
47 | Courier Courier.ttc 0
48 | Courier-Bold Courier.ttc 1
49 | Courier-Oblique Courier.ttc 2
50 |
--------------------------------------------------------------------------------
/tests/data/expected_fontPath.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_fontPath.pdf
--------------------------------------------------------------------------------
/tests/data/expected_fontPath.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_fontPath.png
--------------------------------------------------------------------------------
/tests/data/expected_fontVariations.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_fontVariations.pdf
--------------------------------------------------------------------------------
/tests/data/expected_fontVariations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_fontVariations.png
--------------------------------------------------------------------------------
/tests/data/expected_fontVariations.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello Q
6 |
7 |
8 |
9 |
10 | Hello Q
11 |
12 |
13 |
14 |
15 | Hello Q
16 |
17 |
18 |
19 |
20 | Hello Q
21 |
22 |
23 |
24 |
25 | Hello Q
26 |
27 |
28 |
29 |
30 | Hello Q
31 |
32 |
33 |
--------------------------------------------------------------------------------
/tests/data/expected_fontVariations.txt:
--------------------------------------------------------------------------------
1 | *** DrawBot warning: fontVariations(None) is deprecated, use fontVariations(resetVariations=True) instead. ***
2 | wdth [('defaultValue', 1.0), ('maxValue', 1.3), ('minValue', 0.62), ('name', 'Width')]
3 | wght [('defaultValue', 1.0), ('maxValue', 3.2), ('minValue', 0.48), ('name', 'Weight')]
4 |
--------------------------------------------------------------------------------
/tests/data/expected_fontVariations2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_fontVariations2.pdf
--------------------------------------------------------------------------------
/tests/data/expected_fontVariations2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_fontVariations2.png
--------------------------------------------------------------------------------
/tests/data/expected_fontVariations2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hello Q
6 |
7 |
8 | Hello Q
9 |
10 |
11 | Hello Q
12 |
13 |
14 | Hello Q
15 |
16 |
17 | Hello Q
18 |
19 |
20 | Hello Q
21 |
22 |
23 |
--------------------------------------------------------------------------------
/tests/data/expected_fontVariations2.txt:
--------------------------------------------------------------------------------
1 | *** DrawBot warning: fontVariations(None) is deprecated, use fontVariations(resetVariations=True) instead. ***
2 |
--------------------------------------------------------------------------------
/tests/data/expected_formattedStringURL.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | foo
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/tests/data/expected_image.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_image.pdf
--------------------------------------------------------------------------------
/tests/data/expected_image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_image.png
--------------------------------------------------------------------------------
/tests/data/expected_image2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_image2.pdf
--------------------------------------------------------------------------------
/tests/data/expected_image2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_image2.png
--------------------------------------------------------------------------------
/tests/data/expected_image3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_image3.pdf
--------------------------------------------------------------------------------
/tests/data/expected_image3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_image3.png
--------------------------------------------------------------------------------
/tests/data/expected_image4.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_image4.pdf
--------------------------------------------------------------------------------
/tests/data/expected_image4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_image4.png
--------------------------------------------------------------------------------
/tests/data/expected_imageAntiAliasing.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_imageAntiAliasing.png
--------------------------------------------------------------------------------
/tests/data/expected_imageFontSubpixelQuantization.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_imageFontSubpixelQuantization.png
--------------------------------------------------------------------------------
/tests/data/expected_imageHTTP.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_imageHTTP.pdf
--------------------------------------------------------------------------------
/tests/data/expected_imageHTTP.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_imageHTTP.png
--------------------------------------------------------------------------------
/tests/data/expected_imagePixelColor.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_imagePixelColor.pdf
--------------------------------------------------------------------------------
/tests/data/expected_imagePixelColor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_imagePixelColor.png
--------------------------------------------------------------------------------
/tests/data/expected_imagePixelColor.txt:
--------------------------------------------------------------------------------
1 | CG: 0.0 0.0 0.502
2 | PIL: 0.0 0.0 0.502
3 |
4 | CG: 0.0 0.251 0.502
5 | PIL: 0.0 0.251 0.502
6 |
7 | CG: 0.0 0.502 0.502
8 | PIL: 0.0 0.502 0.502
9 |
10 | CG: 0.0 0.749 0.502
11 | PIL: 0.0 0.749 0.502
12 |
13 | CG: 0.251 0.0 0.502
14 | PIL: 0.251 0.0 0.502
15 |
16 | CG: 0.251 0.251 0.502
17 | PIL: 0.251 0.251 0.502
18 |
19 | CG: 0.251 0.502 0.502
20 | PIL: 0.251 0.502 0.502
21 |
22 | CG: 0.251 0.749 0.502
23 | PIL: 0.251 0.749 0.502
24 |
25 | CG: 0.502 0.0 0.502
26 | PIL: 0.502 0.0 0.502
27 |
28 | CG: 0.502 0.251 0.502
29 | PIL: 0.502 0.251 0.502
30 |
31 | CG: 0.502 0.502 0.502
32 | PIL: 0.502 0.502 0.502
33 |
34 | CG: 0.502 0.749 0.502
35 | PIL: 0.502 0.749 0.502
36 |
37 | CG: 0.749 0.0 0.502
38 | PIL: 0.749 0.0 0.502
39 |
40 | CG: 0.749 0.251 0.502
41 | PIL: 0.749 0.251 0.502
42 |
43 | CG: 0.749 0.502 0.502
44 | PIL: 0.749 0.502 0.502
45 |
46 | CG: 0.749 0.749 0.502
47 | PIL: 0.749 0.749 0.502
48 |
49 |
--------------------------------------------------------------------------------
/tests/data/expected_line.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_line.pdf
--------------------------------------------------------------------------------
/tests/data/expected_line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_line.png
--------------------------------------------------------------------------------
/tests/data/expected_line.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/tests/data/expected_linearGradient.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_linearGradient.pdf
--------------------------------------------------------------------------------
/tests/data/expected_linearGradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_linearGradient.png
--------------------------------------------------------------------------------
/tests/data/expected_linearGradient.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_openTypeFeatures.pdf
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_openTypeFeatures.png
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hoefler Fact #123
6 |
7 |
8 |
9 |
10 | Hoefler Fact #123
11 |
12 |
13 |
14 |
15 | Hoefler Fact #123
16 |
17 |
18 |
19 |
20 | Hoefler Fact #123
21 |
22 |
23 |
24 |
25 | Hoefler Fact #123
26 |
27 |
28 |
29 |
30 | Hoefler Fact #123
31 |
32 |
33 |
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures.txt:
--------------------------------------------------------------------------------
1 | ['dlig', 'liga', 'lnum', 'onum', 'pnum', 'titl', 'tnum']
2 | *** DrawBot warning: openTypeFeatures(None) is deprecated, use openTypeFeatures(resetFeatures=True) instead. ***
3 |
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_openTypeFeatures2.pdf
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_openTypeFeatures2.png
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Hoefler Fact #123
6 |
7 |
8 | Hoefler Fact #123
9 |
10 |
11 | Hoefler Fact #123
12 |
13 |
14 | Hoefler Fact #123
15 |
16 |
17 | Hoefler Fact #123
18 |
19 |
20 | Hoefler Fact #123
21 |
22 |
23 | Hoefler Fact #123
24 |
25 |
26 |
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures2.txt:
--------------------------------------------------------------------------------
1 | *** DrawBot warning: openTypeFeatures(None) is deprecated, use openTypeFeatures(resetFeatures=True) instead. ***
2 |
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures_kern.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_openTypeFeatures_kern.pdf
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures_kern.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_openTypeFeatures_kern.png
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures_kern.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ToTAVAT.
6 |
7 |
8 |
9 |
10 | ToTAVAT.
11 |
12 |
13 |
14 |
15 | ToTAVAT.
16 |
17 |
18 |
19 |
20 | ToTAVAT.
21 |
22 |
23 |
24 |
25 | ToTAVAT.
26 |
27 |
28 |
29 |
30 | ToTAVAT.
31 |
32 |
33 |
--------------------------------------------------------------------------------
/tests/data/expected_openTypeFeatures_kern.txt:
--------------------------------------------------------------------------------
1 | *** DrawBot warning: OpenType feature 'kern' not available for 'Times' ***
2 |
--------------------------------------------------------------------------------
/tests/data/expected_oval.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_oval.pdf
--------------------------------------------------------------------------------
/tests/data/expected_oval.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_oval.png
--------------------------------------------------------------------------------
/tests/data/expected_path.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_path.pdf
--------------------------------------------------------------------------------
/tests/data/expected_path.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_path.png
--------------------------------------------------------------------------------
/tests/data/expected_path.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/tests/data/expected_pathWithCounter.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_pathWithCounter.pdf
--------------------------------------------------------------------------------
/tests/data/expected_pathWithCounter.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_pathWithCounter.png
--------------------------------------------------------------------------------
/tests/data/expected_pathWithCounter.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/tests/data/expected_polygon.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_polygon.pdf
--------------------------------------------------------------------------------
/tests/data/expected_polygon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_polygon.png
--------------------------------------------------------------------------------
/tests/data/expected_polygon.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tests/data/expected_radialGradient.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_radialGradient.pdf
--------------------------------------------------------------------------------
/tests/data/expected_radialGradient.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_radialGradient.png
--------------------------------------------------------------------------------
/tests/data/expected_radialGradient.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/tests/data/expected_rect.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_rect.pdf
--------------------------------------------------------------------------------
/tests/data/expected_rect.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_rect.png
--------------------------------------------------------------------------------
/tests/data/expected_rect.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/tests/data/expected_removeOverlap.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_removeOverlap.pdf
--------------------------------------------------------------------------------
/tests/data/expected_removeOverlap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_removeOverlap.png
--------------------------------------------------------------------------------
/tests/data/expected_removeOverlap.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/tests/data/expected_save.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_save.pdf
--------------------------------------------------------------------------------
/tests/data/expected_save.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_save.png
--------------------------------------------------------------------------------
/tests/data/expected_save.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/tests/data/expected_save1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_save1.pdf
--------------------------------------------------------------------------------
/tests/data/expected_save1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_save1.png
--------------------------------------------------------------------------------
/tests/data/expected_save1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tests/data/expected_savedState.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_savedState.pdf
--------------------------------------------------------------------------------
/tests/data/expected_savedState.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_savedState.png
--------------------------------------------------------------------------------
/tests/data/expected_savedState.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/tests/data/expected_savedState1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_savedState1.pdf
--------------------------------------------------------------------------------
/tests/data/expected_savedState1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_savedState1.png
--------------------------------------------------------------------------------
/tests/data/expected_savedState1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/tests/data/expected_shapes.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_shapes.pdf
--------------------------------------------------------------------------------
/tests/data/expected_shapes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_shapes.png
--------------------------------------------------------------------------------
/tests/data/expected_shapes.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/tests/data/expected_svgLinkURL.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/tests/data/expected_svgMixin.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | world
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/tests/data/expected_svgSaveFallback.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | a
6 |
7 |
8 |
--------------------------------------------------------------------------------
/tests/data/expected_text.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_text.pdf
--------------------------------------------------------------------------------
/tests/data/expected_text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_text.png
--------------------------------------------------------------------------------
/tests/data/expected_text.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | hello world
6 |
7 |
8 |
9 |
10 | foo bar
11 |
12 |
13 |
14 |
15 | foo bar
16 |
17 |
18 |
19 |
20 |
21 | foo bar
22 |
23 |
24 |
25 |
26 | foo bar
27 |
28 |
29 |
30 |
31 | foo bar
32 |
33 |
34 |
--------------------------------------------------------------------------------
/tests/data/expected_text2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_text2.pdf
--------------------------------------------------------------------------------
/tests/data/expected_text2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_text2.png
--------------------------------------------------------------------------------
/tests/data/expected_textBox.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_textBox.pdf
--------------------------------------------------------------------------------
/tests/data/expected_textBox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_textBox.png
--------------------------------------------------------------------------------
/tests/data/expected_textBox.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Hello there,
7 |
8 |
9 | hi people,
10 |
11 |
12 | dear reader.
13 |
14 |
15 |
16 |
17 |
18 | Hello there,
19 |
20 |
21 | hi people,
22 |
23 |
24 | dear reader.
25 |
26 |
27 |
--------------------------------------------------------------------------------
/tests/data/expected_textBoxLongText.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_textBoxLongText.pdf
--------------------------------------------------------------------------------
/tests/data/expected_textBoxLongText.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_textBoxLongText.png
--------------------------------------------------------------------------------
/tests/data/expected_textBoxLongText.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fiflfiflfiflfiflfiflfiflfiflfiflfi
6 |
7 |
8 | flfiflfiflfiflfiflfiflfiflfiflfifl
9 |
10 |
11 | fiflfiflfiflfiflfiflfiflfiflfiflfi
12 |
13 |
14 | flfiflfiflfiflfiflfiflfiflfiflfifl
15 |
16 |
17 | fiflfiflfiflfiflfiflfiflfiflfiflfi
18 |
19 |
20 | flfiflfiflfiflfiflfiflfiflfiflfifl
21 |
22 |
23 | fiflfiflfiflfiflfiflfiflfiflfiflfi
24 |
25 |
26 | flfiflfiflfiflfiflfiflfiflfiflfifl
27 |
28 |
29 |
--------------------------------------------------------------------------------
/tests/data/expected_traceback.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_traceback.pdf
--------------------------------------------------------------------------------
/tests/data/expected_traceback.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/expected_traceback.png
--------------------------------------------------------------------------------
/tests/data/expected_traceback.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/tests/data/expected_traceback.txt:
--------------------------------------------------------------------------------
1 | Traceback (most recent call last):
2 | ...
3 | ZeroDivisionError: division by zero
4 |
--------------------------------------------------------------------------------
/tests/data/fontVariations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/typemytype/drawbot/68255e32cba97b0fcc65507f3fdd1598f42b9150/tests/data/fontVariations.png
--------------------------------------------------------------------------------
/tests/data/scriptRunnerTest.py:
--------------------------------------------------------------------------------
1 | # test file used by testMisc.MiscTest.test_ScriptRunner_fromPath
2 | print(__file__)
3 | print(__name__)
4 | print("Åbenrå")
5 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/appendGlyphWithFontVariations.py:
--------------------------------------------------------------------------------
1 | # https://github.com/typemytype/drawbot/issues/402
2 | import drawBot
3 |
4 | drawBot.size(640, 160)
5 |
6 | fs = drawBot.FormattedString()
7 | fs.font("Skia")
8 | fs.fontSize(200)
9 | fs.fontVariations(wght=1)
10 | fs += "&"
11 | fs.appendGlyph("ampersand")
12 | fs.fontVariations(wght=2)
13 | fs.appendGlyph("ampersand")
14 | fs += "&"
15 |
16 | drawBot.text(fs, (10, 10))
17 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/appendGlyphWithTracking.py:
--------------------------------------------------------------------------------
1 | # https://github.com/typemytype/drawbot/issues/427
2 | import drawBot
3 |
4 | drawBot.size(200, 200)
5 |
6 | fs = drawBot.FormattedString()
7 | fs.font("Lucida Grande")
8 | fs.fontSize(50)
9 | fs.appendGlyph("H")
10 | fs.appendGlyph("i")
11 | drawBot.text(fs, (30, 110))
12 |
13 | fs = drawBot.FormattedString()
14 | fs.font("Lucida Grande")
15 | fs.fontSize(50)
16 | fs.tracking(10)
17 | fs.appendGlyph("H")
18 | fs.appendGlyph("i")
19 | drawBot.text(fs, (30, 50))
20 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/booleanOperations.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.newDrawing()
4 | drawBot.size(600, 100)
5 | p1 = drawBot.BezierPath()
6 | p1.oval(5, 5, 70, 70)
7 | p2 = drawBot.BezierPath()
8 | p2.rect(25, 25, 70, 70)
9 | drawBot.fill(0, 0.3)
10 | drawBot.stroke(0)
11 |
12 | drawBot.drawPath(p1)
13 | drawBot.drawPath(p2)
14 |
15 | pUnion = p1.union(p2)
16 | pIntersection = p1.intersection(p2)
17 | pXor = p1.xor(p2)
18 | pDiff1 = p1.difference(p2)
19 | pDiff2 = p2.difference(p1)
20 |
21 | for p in [pUnion, pIntersection, pXor, pDiff1, pDiff2]:
22 | drawBot.translate(100, 0)
23 | drawBot.drawPath(p)
24 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/booleanOperations2.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.newDrawing()
4 | drawBot.size(600, 100)
5 | p1 = drawBot.BezierPath()
6 | p1.oval(5, 5, 70, 70)
7 | p2 = drawBot.BezierPath()
8 | p2.rect(25, 25, 70, 70)
9 | drawBot.fill(0, 0.3)
10 | drawBot.stroke(0)
11 |
12 | drawBot.drawPath(p1)
13 | drawBot.drawPath(p2)
14 |
15 | pUnion = p1 | p2
16 | pIntersection = p1 & p2
17 | pXor = p1 ^ p2
18 | pDiff1 = p1 % p2
19 | pDiff2 = p2 % p1
20 |
21 | for p in [pUnion, pIntersection, pXor, pDiff1, pDiff2]:
22 | drawBot.translate(100, 0)
23 | drawBot.drawPath(p)
24 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/centeredTransform.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.newDrawing()
4 | drawBot.size(200, 200)
5 |
6 |
7 | def rotateScale(r, s, center):
8 | drawBot.rotate(r, center=center)
9 | drawBot.scale(s, center=center)
10 |
11 |
12 | testData = [
13 | ((25, 25, 50, 50), drawBot.rotate, (20,), (25, 25)),
14 | ((125, 25, 50, 50), drawBot.skew, (10, 10), (175, 25)),
15 | ((25, 125, 50, 50), drawBot.scale, (1.2, 1.4), (25, 175)),
16 | ((125, 125, 50, 50), rotateScale, (20, 0.8), (175, 175)),
17 | ]
18 |
19 | for r, op, args, center in testData:
20 | drawBot.fill(0)
21 | drawBot.rect(*r)
22 | with drawBot.savedState():
23 | drawBot.fill(1, 0, 0, 0.5)
24 | op(*args, center=center)
25 | drawBot.rect(*r)
26 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/centeredTransformBezierPath.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.newDrawing()
4 | drawBot.size(200, 200)
5 |
6 | testData = [
7 | ((25, 25, 50, 50), "rotate", (20,), (25, 25)),
8 | ((125, 25, 50, 50), "skew", (10, 10), (175, 25)),
9 | ((25, 125, 50, 50), "scale", (1.2, 1.4), (25, 175)),
10 | ]
11 |
12 | for r, op, args, center in testData:
13 | drawBot.fill(0)
14 | bez = drawBot.BezierPath()
15 | bez.rect(*r)
16 | drawBot.drawPath(bez)
17 | with drawBot.savedState():
18 | drawBot.fill(1, 0, 0, 0.5)
19 | bez = drawBot.BezierPath()
20 | bez.rect(*r)
21 | getattr(bez, op)(*args, center=center)
22 | drawBot.drawPath(bez)
23 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/cmykFill.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(100, 100)
4 | for x in range(10):
5 | for y in range(10):
6 | drawBot.cmykFill(x / 10, 1 - y / 10, y / 10, 0)
7 | drawBot.rect(x * 10, y * 10, 5, 10)
8 | drawBot.cmykFill(x / 10, 1 - y / 10, y / 10, 0.2)
9 | drawBot.rect(x * 10 + 5, y * 10, 5, 5)
10 | drawBot.cmykFill(x / 10, 1 - y / 10, y / 10, 0, 0.55)
11 | drawBot.rect(x * 10 + 5, y * 10 + 5, 5, 5)
12 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/cmykLinearGradient.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | drawBot.cmykLinearGradient(
5 | (100, 100), # startPoint
6 | (200, 200), # endPoint
7 | [(1, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, 0.2)], # cmyk colors
8 | [0, 0.2, 1], # locations
9 | )
10 | drawBot.rect(0, 0, 200, 200)
11 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/cmykRadialGradient.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | drawBot.cmykRadialGradient(
5 | (0, 0), # startPoint
6 | (200, 200), # endPoint
7 | [(1, 0, 0, 1), (0, 0, 1, 0), (0, 1, 0, 0.2)], # colors
8 | [0, 0.2, 1], # locations
9 | 0, # startRadius
10 | 200, # endRadius
11 | )
12 | drawBot.rect(0, 0, 200, 200)
13 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/dashStroke.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.newDrawing()
4 | drawBot.newPage(40, 40)
5 | path = drawBot.BezierPath()
6 | path.rect(10, 10, 20, 20)
7 |
8 | dashedPath = path.dashStroke(5, 5)
9 |
10 | drawBot.fill(None)
11 | drawBot.stroke(0)
12 | drawBot.drawPath(dashedPath)
13 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/fill.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(100, 100)
4 | drawBot.fill(0.5, 0.5)
5 | drawBot.oval(0, 0, 100, 100)
6 | for x in range(10):
7 | for y in range(10):
8 | drawBot.fill(x / 10, 1 - y / 10, y / 10, y / 20 + 0.5)
9 | drawBot.rect(x * 10, y * 10, 10, 10)
10 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/fontAttributes.py:
--------------------------------------------------------------------------------
1 | import os
2 |
3 | import drawBot
4 |
5 | drawBot.size(50, 50)
6 | characters = "Aa今"
7 | glyphNames = ["A", "a", "zzz"]
8 | for fontName in ["Times", "../data/MutatorSans.ttf"]:
9 | print(fontName)
10 | print(drawBot.font(fontName))
11 | drawBot.fontSize(50)
12 | for char in characters:
13 | print(drawBot.fontContainsCharacters(char))
14 | for glyphName in glyphNames:
15 | print(drawBot.fontContainsGlyph(glyphName))
16 | print(os.path.basename(drawBot.fontFilePath()))
17 | print(drawBot.listFontGlyphNames()[:6])
18 | print(drawBot.fontAscender())
19 | print(drawBot.fontDescender())
20 | print(drawBot.fontXHeight())
21 | print(drawBot.fontCapHeight())
22 | print(drawBot.fontLeading())
23 | print(drawBot.fontLineHeight())
24 | print()
25 |
26 | # https://github.com/typemytype/drawbot/issues/524
27 | print(drawBot.font("Apple Color Emoji"))
28 | print(drawBot.fontContainsCharacters(chr(0x1F004)))
29 | print()
30 |
31 | for i in range(4):
32 | print(drawBot.font("../data/MutatorSans.ttc", fontNumber=i))
33 | print(os.path.basename(drawBot.fontFilePath()), drawBot.fontFileFontNumber())
34 | assert drawBot.fontFileFontNumber() == i
35 |
36 | print()
37 | for fontName in ["Courier", "Courier-Bold", "Courier-Oblique"]:
38 | drawBot.font(fontName)
39 | print(fontName, os.path.basename(drawBot.fontFilePath()), drawBot.fontFileFontNumber())
40 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/fontPath.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(500, 70)
4 | fontPath = "../data/MutatorSans.ttf"
5 | drawBot.font(fontPath)
6 | drawBot.fontSize(20)
7 | drawBot.text("HELLO MUTATOR", (10, 10))
8 | drawBot.fontVariations(wdth=500, wght=900)
9 | drawBot.text("HELLO MUTATOR", (10, 40))
10 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/fontVariations.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 |
5 | drawBot.font("Skia")
6 | drawBot.fontSize(30)
7 |
8 | drawBot.fontVariations(None)
9 |
10 | variations = drawBot.listFontVariations()
11 | for axisTag in sorted(variations):
12 | data = variations[axisTag]
13 | # we're rounding the values so we don't trip over small differences between OSes
14 | data["defaultValue"] = round(float(data["defaultValue"]), 3) # we need floats to make sure that 1 becomes 1.0
15 | data["minValue"] = round(float(data["minValue"]), 3)
16 | data["maxValue"] = round(float(data["maxValue"]), 3)
17 | data["name"] = str(data["name"])
18 | print(axisTag, [(k, data[k]) for k in sorted(data)])
19 |
20 | drawBot.text("Hello Q", (20, 170))
21 | drawBot.fontVariations(wght=0.6)
22 | drawBot.text("Hello Q", (20, 140))
23 | drawBot.fontVariations(wght=2.4)
24 | drawBot.text("Hello Q", (20, 110))
25 |
26 | drawBot.fontVariations(wdth=1.29)
27 | drawBot.text("Hello Q", (20, 80))
28 |
29 | drawBot.fontVariations(wdth=0.6, resetVariations=True)
30 | drawBot.text("Hello Q", (20, 50))
31 |
32 | drawBot.fontVariations(wght=2.8, resetVariations=False)
33 | drawBot.text("Hello Q", (20, 20))
34 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/fontVariations2.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 |
5 | s = drawBot.FormattedString()
6 |
7 | s.font("Skia")
8 | s.fontSize(30)
9 | s.lineHeight(30)
10 | s.fontVariations(None)
11 |
12 | s.append("Hello Q\n")
13 | s.fontVariations(wght=0.6)
14 | s.append("Hello Q\n")
15 | s.fontVariations(wght=2.4)
16 | s.append("Hello Q\n")
17 |
18 | s.append("Hello Q\n", fontVariations=dict(wdth=1.29))
19 |
20 | s.append("Hello Q\n", fontVariations=dict(wdth=0.6, resetVariations=True))
21 |
22 | s.fontVariations(wght=2.8, resetVariations=False)
23 | s.append("Hello Q\n")
24 |
25 | drawBot.textBox(s, (10, 0, 190, 193))
26 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/image.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(500, 500)
4 | imagePath = "../data/drawBot.jpg"
5 | w, h = drawBot.imageSize(imagePath)
6 | drawBot.scale(250 / w)
7 | drawBot.image(imagePath, (0, 0))
8 | drawBot.image(imagePath, (w, 0), alpha=0.5)
9 | drawBot.image(imagePath, (0, h), alpha=0.25)
10 | drawBot.image(imagePath, (w, h), alpha=0.75)
11 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/image2.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(500, 500)
4 | imagePath = "../data/drawBot.png"
5 | w, h = drawBot.imageSize(imagePath)
6 | drawBot.scale(250 / w)
7 | drawBot.image(imagePath, (0, 0))
8 | drawBot.image(imagePath, (w, 0), alpha=0.5)
9 | drawBot.image(imagePath, (0, h), alpha=0.25)
10 | drawBot.image(imagePath, (w, h), alpha=0.75)
11 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/image3.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(500, 500)
4 | imagePath = "../data/drawBot.pdf"
5 | w, h = drawBot.imageSize(imagePath)
6 | drawBot.scale(250 / w)
7 | drawBot.image(imagePath, (0, 0))
8 | drawBot.image(imagePath, (w, 0), alpha=0.5)
9 | drawBot.image(imagePath, (0, h), alpha=0.25)
10 | drawBot.image(imagePath, (w, h), alpha=0.75)
11 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/image4.py:
--------------------------------------------------------------------------------
1 | import pathlib
2 |
3 | import drawBot
4 |
5 | drawBot.size(500, 500)
6 | imagePath = "../data/drawBot.pdf"
7 | w, h = drawBot.imageSize(imagePath)
8 | drawBot.save()
9 | drawBot.scale(250 / w)
10 | drawBot.image(imagePath, (0, 0))
11 | drawBot.restore()
12 |
13 | imagePath = "../data/drawBot.png"
14 | w, h = drawBot.imageSize(imagePath)
15 | drawBot.save()
16 | drawBot.scale(250 / w)
17 | drawBot.image(imagePath, (w, 0))
18 | drawBot.restore()
19 |
20 | imagePath = "../data/drawBot.jpg"
21 | w, h = drawBot.imageSize(imagePath)
22 | drawBot.save()
23 | drawBot.scale(250 / w)
24 | drawBot.image(imagePath, (0, h))
25 | drawBot.restore()
26 |
27 | imagePath = "../data/drawBot.bmp"
28 | w, h = drawBot.imageSize(imagePath)
29 | drawBot.save()
30 | drawBot.scale(250 / w)
31 | drawBot.image(pathlib.Path(imagePath), (w, h)) # verify that pathlib.Path objects work
32 | drawBot.restore()
33 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/imageHTTP.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(250, 250)
4 | imagePath = "https://github.com/typemytype/drawbot/raw/master/docs/content/assets/drawBot.jpg"
5 | drawBot.scale(250 / 700)
6 | drawBot.image(imagePath, (20, 20))
7 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/imagePixelColor.py:
--------------------------------------------------------------------------------
1 | # This is a test case derived from https://github.com/typemytype/drawbot/issues/171
2 | # It ensures that rgb values specified in fill() end up in image output without
3 | # being mangled by a color space (within 8-bit resulution).
4 |
5 | from PIL import Image
6 |
7 | import drawBot
8 |
9 | canvasSize = 400
10 | drawBot.size(canvasSize, canvasSize)
11 |
12 | # colorSpace("sRGB")
13 | # colorSpace("genericRGB")
14 | # colorSpace("adobeRGB1998")
15 |
16 | bands = 4
17 | bandWidth = canvasSize / bands
18 |
19 | drawBot.fontSize(10)
20 |
21 | for i in range(bands):
22 | x = i * bandWidth
23 | for j in range(bands):
24 | y = j * bandWidth
25 | r = i / bands
26 | g = j / bands
27 | b = 0.5
28 | drawBot.fill(r, g, b)
29 | drawBot.rect(x, y, bandWidth, bandWidth)
30 | drawBot.fill(0)
31 | drawBot.text("%s,%s,%s" % (r, g, b), (x + 3, y + 5))
32 |
33 | fn = "../tempTestData/tmp_imagePixelColor.png"
34 | drawBot.saveImage(fn)
35 |
36 | im = Image.open(fn)
37 |
38 | for i in range(bands):
39 | x = (i + 0.5) * bandWidth
40 | for j in range(bands):
41 | y = (j + 0.5) * bandWidth
42 | r, g, b, a = drawBot.imagePixelColor(fn, (x, y))
43 | print(" CG:", round(r, 4), round(g, 4), round(b, 4))
44 | r, g, b, a = im.getpixel((x, canvasSize - y))
45 | print("PIL:", round(r / 255, 4), round(g / 255, 4), round(b / 255, 4))
46 | print()
47 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/line.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | drawBot.stroke(0)
5 | drawBot.strokeWidth(10)
6 | drawBot.fill(None)
7 | drawBot.line((40, 40), (40, 160))
8 | drawBot.line((100, 40), (160, 160))
9 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/linearGradient.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | drawBot.linearGradient(
5 | (100, 100), # startPoint
6 | (200, 200), # endPoint
7 | [(1, 0, 0), (0, 0, 1), (0, 1, 0)], # colors
8 | [0, 0.2, 1], # locations
9 | )
10 | drawBot.rect(0, 0, 200, 200)
11 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/openTypeFeatures.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 |
5 | # ['liga', 'dlig', 'tnum', 'pnum', 'titl', 'onum', 'lnum']
6 |
7 | drawBot.font("HoeflerText-Regular")
8 | drawBot.fontSize(20)
9 | print(drawBot.listOpenTypeFeatures())
10 |
11 | drawBot.text("Hoefler Fact #123", (20, 170))
12 |
13 | drawBot.openTypeFeatures(None)
14 |
15 | drawBot.openTypeFeatures(dlig=True)
16 | drawBot.text("Hoefler Fact #123", (20, 140))
17 |
18 | drawBot.openTypeFeatures(lnum=True)
19 | drawBot.text("Hoefler Fact #123", (20, 110))
20 |
21 | drawBot.openTypeFeatures(liga=False)
22 | drawBot.text("Hoefler Fact #123", (20, 80))
23 |
24 | drawBot.openTypeFeatures(liga=True, resetFeatures=False)
25 | drawBot.text("Hoefler Fact #123", (20, 50))
26 |
27 | drawBot.openTypeFeatures(liga=False, resetFeatures=True)
28 | drawBot.text("Hoefler Fact #123", (20, 20))
29 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/openTypeFeatures2.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 |
5 | s = drawBot.FormattedString()
6 | s.font("HoeflerText-Regular")
7 | s.fontSize(20)
8 |
9 | s.append("Hoefler Fact #123\n")
10 |
11 | s.openTypeFeatures(None)
12 |
13 | s.openTypeFeatures(dlig=True)
14 | s.append("Hoefler Fact #123\n")
15 |
16 | s.openTypeFeatures(lnum=True)
17 | s.append("Hoefler Fact #123\n")
18 |
19 | s.openTypeFeatures(liga=False)
20 | s.append("Hoefler Fact #123\n")
21 |
22 | s.openTypeFeatures(liga=False, dlig=True, resetFeatures=True)
23 | s.append("Hoefler Fact #123\n")
24 |
25 | s.append("Hoefler Fact #123\n", openTypeFeatures=dict(liga=False, resetFeatures=True))
26 |
27 | s.append("Hoefler Fact #123\n", openTypeFeatures=dict(dlig=True, resetFeatures=False))
28 |
29 | drawBot.textBox(s, (20, 0, 200, 190))
30 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/openTypeFeatures_kern.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.newPage(130, 130)
4 | drawBot.font("Times")
5 | drawBot.text("ToTAVAT.", (10, 10))
6 | drawBot.openTypeFeatures(kern=False)
7 | drawBot.text("ToTAVAT.", (10, 30))
8 | drawBot.openTypeFeatures(kern=True)
9 | drawBot.text("ToTAVAT.", (10, 50))
10 | # add tracking
11 | drawBot.tracking(10)
12 | drawBot.text("ToTAVAT.", (10, 70))
13 | drawBot.openTypeFeatures(kern=False)
14 | drawBot.text("ToTAVAT.", (10, 90))
15 | drawBot.openTypeFeatures(kern=True)
16 | drawBot.text("ToTAVAT.", (10, 110))
17 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/oval.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | for i in range(14):
5 | f = i / 14.0
6 | drawBot.fill(1 - f, 1 - f, 0)
7 | drawBot.oval(10, 10, 50, 50)
8 | drawBot.translate(10, 10)
9 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/path.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 |
5 | drawBot.newPath()
6 | drawBot.moveTo((20, 20))
7 | drawBot.lineTo((20, 100))
8 | drawBot.lineTo((100, 100))
9 | drawBot.lineTo((100, 180))
10 | drawBot.curveTo((150, 180), (180, 150), (180, 100))
11 | drawBot.lineTo((180, 50))
12 | drawBot.qCurveTo((180, 20), (150, 20))
13 |
14 | drawBot.fill(1, 0, 0)
15 | drawBot.stroke(0)
16 | drawBot.strokeWidth(10)
17 | drawBot.drawPath()
18 |
19 | drawBot.closePath()
20 |
21 | drawBot.fill(None)
22 | drawBot.stroke(1)
23 | drawBot.translate(40, 15)
24 | drawBot.scale(0.7)
25 | drawBot.lineCap("round")
26 | drawBot.lineJoin("round")
27 |
28 | drawBot.drawPath()
29 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/pathWithCounter.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 |
5 | drawBot.newPath()
6 | drawBot.moveTo((20, 20))
7 | drawBot.lineTo((20, 100))
8 | drawBot.lineTo((100, 100))
9 | drawBot.lineTo((100, 180))
10 | drawBot.curveTo((150, 180), (180, 150), (180, 100))
11 | drawBot.lineTo((180, 20))
12 | drawBot.closePath()
13 |
14 | drawBot.moveTo((40, 40))
15 | drawBot.lineTo((160, 40))
16 | drawBot.curveTo((160, 65), (145, 80), (120, 80))
17 | drawBot.lineTo((40, 80))
18 | drawBot.closePath()
19 |
20 | drawBot.fill(0.5, 0, 0)
21 | drawBot.stroke(None)
22 | drawBot.strokeWidth(10)
23 | drawBot.drawPath()
24 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/polygon.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | drawBot.stroke(0)
5 | drawBot.strokeWidth(10)
6 | drawBot.fill(1, 0.3, 0)
7 | drawBot.polygon((40, 40), (40, 160))
8 | drawBot.polygon((60, 40), (60, 160), (130, 160))
9 | drawBot.polygon((100, 40), (160, 160), (160, 40), close=False)
10 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/radialGradient.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | drawBot.radialGradient(
5 | (0, 0), # startPoint
6 | (200, 200), # endPoint
7 | [(1, 0, 0), (0, 0, 1), (0, 1, 0)], # colors
8 | [0, 0.2, 1], # locations
9 | 0, # startRadius
10 | 200, # endRadius
11 | )
12 | drawBot.rect(0, 0, 200, 200)
13 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/rect.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | for i in range(14):
5 | f = i / 14.0
6 | drawBot.fill(f, 1 - f, 0)
7 | drawBot.rect(10, 10, 50, 50)
8 | drawBot.translate(10, 10)
9 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/removeOverlap.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.newDrawing()
4 | drawBot.size(200, 100)
5 | p = drawBot.BezierPath()
6 | p.oval(5, 5, 70, 70)
7 | p.rect(25, 25, 70, 70)
8 | drawBot.fill(0, 0.3)
9 | drawBot.stroke(0)
10 | drawBot.drawPath(p)
11 | p.removeOverlap()
12 | drawBot.translate(100, 0)
13 | drawBot.drawPath(p)
14 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/save.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | drawBot.stroke(0, 0, 1)
5 | drawBot.strokeWidth(5)
6 | drawBot.save()
7 | drawBot.fill(1, 0, 0)
8 | drawBot.translate(100, 100)
9 | drawBot.rect(0, 0, 100, 100)
10 | drawBot.restore()
11 | drawBot.rect(0, 0, 100, 100)
12 | drawBot.save()
13 | drawBot.fill(0, 1, 0)
14 | drawBot.translate(100, 0)
15 | drawBot.rect(0, 0, 100, 100)
16 | drawBot.restore()
17 | drawBot.rect(0, 100, 100, 100)
18 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/save1.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(300, 300)
4 | drawBot.save()
5 | drawBot.fill(1, 0, 0)
6 | drawBot.translate(150, 150)
7 | drawBot.rect(0, 0, 100, 100)
8 | drawBot.save()
9 | drawBot.rotate(45)
10 | drawBot.fill(0, 1, 0)
11 | drawBot.rect(0, 0, 100, 100)
12 | drawBot.restore()
13 | drawBot.restore()
14 | drawBot.rect(0, 0, 100, 100)
15 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/savedState.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | drawBot.stroke(0, 0, 1)
5 | drawBot.strokeWidth(5)
6 | with drawBot.savedState():
7 | drawBot.fill(1, 0, 0)
8 | drawBot.translate(100, 100)
9 | drawBot.rect(0, 0, 100, 100)
10 | drawBot.rect(0, 0, 100, 100)
11 | with drawBot.savedState():
12 | drawBot.fill(0, 1, 0)
13 | drawBot.translate(100, 0)
14 | drawBot.rect(0, 0, 100, 100)
15 | drawBot.rect(0, 100, 100, 100)
16 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/savedState1.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(300, 300)
4 | with drawBot.savedState():
5 | drawBot.fill(1, 0, 0)
6 | drawBot.translate(150, 150)
7 | drawBot.rect(0, 0, 100, 100)
8 | with drawBot.savedState():
9 | drawBot.rotate(45)
10 | drawBot.fill(0, 1, 0)
11 | drawBot.rect(0, 0, 100, 100)
12 | drawBot.rect(0, 0, 100, 100)
13 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/shapes.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | drawBot.fill(0)
5 | drawBot.rect(10, 10, 100, 100)
6 | drawBot.fill(None)
7 | drawBot.stroke(1, 0, 0)
8 | drawBot.strokeWidth(5)
9 | drawBot.oval(50, 50, 100, 100)
10 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/text.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | drawBot.text("hello world", (10, 10))
5 | drawBot.fill(1, 0, 0)
6 | drawBot.text("foo bar", (10, 30))
7 | drawBot.fill(1, 0, 1)
8 | drawBot.stroke(0, 1, 0)
9 | drawBot.strokeWidth(2)
10 | drawBot.font("Times", 50)
11 | drawBot.text("foo bar", (10, 50))
12 | drawBot.fill(None)
13 | drawBot.stroke(0, 1, 0)
14 | drawBot.strokeWidth(1)
15 | drawBot.line((0, 50), (drawBot.width(), 50))
16 | drawBot.stroke(None)
17 | drawBot.fill(0, 1, 1)
18 | drawBot.fontSize(20)
19 | drawBot.text("foo bar", (drawBot.width() * 0.5, 100), align="right")
20 | drawBot.text("foo bar", (drawBot.width() * 0.5, 120), align="center")
21 | drawBot.text("foo bar", (drawBot.width() * 0.5, 140), align="left")
22 | # test empty text https://github.com/typemytype/drawbot/issues/389
23 | drawBot.text("", (0, 0))
24 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/text2.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | f = drawBot.FormattedString()
4 | f.fontSize(40)
5 | f.font("Helvetica")
6 | f.align("left")
7 | f.append("left\n")
8 | f.align("center")
9 | f.append("center\n")
10 | f.font("Times")
11 | f.align("right")
12 | f.append("right\n")
13 |
14 | _, height = f.size()
15 | x, y = drawBot.width() * 0.25, 200.0
16 |
17 | with drawBot.savedState():
18 | drawBot.stroke(0)
19 | drawBot.line((x, 0), (x, 1000))
20 |
21 |
22 | drawBot.text(f, (x, y))
23 | y += height
24 | drawBot.text(f, (x, y), align="left")
25 | y += height
26 | drawBot.text(f, (x, y), align="center")
27 | y += height
28 | drawBot.text(f, (x, y), align="right")
29 |
30 | x, y = drawBot.width() * 0.75, 200
31 | with drawBot.savedState():
32 | drawBot.stroke(0)
33 | drawBot.line((x, 0), (x, 1000))
34 |
35 | b = drawBot.BezierPath()
36 | b.text(f)
37 | b.text(f, offset=(0, height), align="left")
38 | b.text(f, offset=(0, height * 2), align="center")
39 | b.text(f, offset=(0, height * 3), align="right")
40 | drawBot.translate(x, y)
41 | drawBot.fill(1, 0, 0)
42 | drawBot.drawPath(b)
43 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/textBox.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 400)
4 | box = (10, 10, 180, 180)
5 | drawBot.fill(0)
6 | drawBot.rect(*box)
7 | drawBot.fill(1)
8 | drawBot.fontSize(30)
9 | drawBot.textBox("Hello there, hi people, dear reader.", box)
10 | drawBot.translate(0, 200)
11 | box = (190, 190, -180, -180)
12 | drawBot.fill(0)
13 | drawBot.rect(*box)
14 | drawBot.fill(1)
15 | drawBot.textBox("Hello there, hi people, dear reader.", box)
16 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/textBoxLongText.py:
--------------------------------------------------------------------------------
1 | # See bug: https://github.com/typemytype/drawbot/issues/585
2 | import drawBot
3 |
4 | drawBot.size(200, 200)
5 | box = (10, 10, 180, 180)
6 | drawBot.fontSize(18)
7 | drawBot.font("Hoefler Text")
8 | drawBot.textBox("fifl" * 3000, box)
9 |
--------------------------------------------------------------------------------
/tests/drawBotScripts/traceback.py:
--------------------------------------------------------------------------------
1 | import drawBot
2 |
3 | drawBot.size(200, 200)
4 | 1 / 0
5 |
--------------------------------------------------------------------------------
/tests/package/empty.drawbot/lib/main.py:
--------------------------------------------------------------------------------
1 | print("hello world")
2 |
--------------------------------------------------------------------------------
/tests/package/missingMainScript.drawbot/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | developer
6 | drawbot
7 | developerURL
8 | http://www.drawbot.com
9 | name
10 | drawbot
11 | requiresVersion
12 | 3.0
13 | version
14 | 1.0
15 |
16 |
17 |
--------------------------------------------------------------------------------
/tests/package/simple.drawbot/info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | developer
6 | drawbot
7 | developerURL
8 | http://www.drawbot.com
9 | name
10 | drawbot
11 | requiresVersion
12 | 3.0
13 | version
14 | 1.0
15 |
16 |
17 |
--------------------------------------------------------------------------------
/tests/package/simple.drawbot/lib/main.py:
--------------------------------------------------------------------------------
1 | print("hello world")
2 |
--------------------------------------------------------------------------------
/tests/runAllTests.py:
--------------------------------------------------------------------------------
1 | import doctest
2 | import glob
3 | import importlib
4 | import os
5 | import sys
6 | import unittest
7 |
8 | inDrawBotApp = "drawBot.ui.codeEditor" in sys.modules
9 |
10 | testRootDir = os.path.dirname(os.path.abspath(__file__))
11 | if testRootDir not in sys.path:
12 | sys.path.append(testRootDir)
13 |
14 | testModules = glob.glob(os.path.join(testRootDir, "test*.py"))
15 | modulesWithDocTests = ["drawBot.misc", "testSupport"] # TODO: doctest discovery
16 |
17 | loader = unittest.TestLoader()
18 | suite = unittest.TestSuite()
19 | for path in testModules:
20 | moduleName, ext = os.path.splitext(os.path.basename(path))
21 | suite.addTest(loader.loadTestsFromName(moduleName))
22 |
23 | for moduleName in modulesWithDocTests:
24 | m = importlib.import_module(moduleName)
25 | suite.addTest(doctest.DocTestSuite(m))
26 |
27 | result = unittest.TextTestRunner(verbosity=1).run(suite)
28 | if not inDrawBotApp and not result.wasSuccessful():
29 | sys.exit(1)
30 |
--------------------------------------------------------------------------------
/tests/testAutomaticallyGeneratedCode.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import unittest
3 | from pathlib import Path
4 |
5 | sys.path.append(str((Path(__file__).parent.parent / "scripting").resolve()))
6 |
7 | from generateDrawbotInit import INIT_PATH, generateInitCode
8 | from imageObjectCodeExtractor import IMAGE_OBJECT_PATH, generateImageObjectCode
9 |
10 |
11 | class AutomaticallyGeneratedCodeTester(unittest.TestCase):
12 | def test_init(self):
13 | initCode = generateInitCode()
14 | self.assertEqual(INIT_PATH.read_text(), initCode)
15 |
16 | def test_imageObject(self):
17 | imageObjectCode, _ = generateImageObjectCode()
18 | self.assertEqual(IMAGE_OBJECT_PATH.read_text(), imageObjectCode)
19 |
20 |
21 | if __name__ == "__main__":
22 | import doctest
23 |
24 | doctest.testmod()
25 | sys.exit(unittest.main())
26 |
--------------------------------------------------------------------------------
/tests/testPackage.py:
--------------------------------------------------------------------------------
1 | import os
2 | import sys
3 | import unittest
4 |
5 | from testSupport import StdOutCollector, TempFile, TempFolder
6 |
7 | from drawBot.drawBotPackage import DrawBotPackage
8 |
9 |
10 | class PackageTest(unittest.TestCase):
11 | def test_buildPackage(self):
12 | package = DrawBotPackage()
13 | package.info.name = "demo"
14 | package.info.developer = "drawbot"
15 | package.info.developerURL = "http://www.drawbot.com"
16 | package.info.requiresVersion = "3.0"
17 | package.info.mainScript = "main.py"
18 |
19 | succes, _ = package.buildPackage("does/not/exists", "does/not/exists")
20 | self.assertFalse(succes)
21 |
22 | with TempFolder(suffix=".drawbot") as tempPath:
23 | succes, _ = package.buildPackage(tempPath.path, "does/not/exists")
24 | self.assertFalse(succes)
25 |
26 | with TempFolder() as tempScriptRoot:
27 | succes, _ = package.buildPackage(tempPath.path, tempScriptRoot.path)
28 | self.assertFalse(succes)
29 |
30 | with TempFile(suffix=".py", dir=tempScriptRoot.path) as tmp:
31 | with open(tmp.path, "w") as f:
32 | f.write("print('hello world'")
33 | package.info.mainScript = os.path.basename(tmp.path)
34 | succes, _ = package.buildPackage(tempPath.path, tempScriptRoot.path)
35 | self.assertTrue(succes)
36 |
37 | def test_readPackage(self):
38 | path = os.path.join(os.path.dirname(__file__), "package/empty.drawbot")
39 |
40 | package = DrawBotPackage(path)
41 | self.assertEqual(package.info.asDict(), {})
42 | self.assertEqual(package.info.version, "0.0")
43 | self.assertEqual(package.info.developer, "")
44 | self.assertEqual(package.info.developerURL, "")
45 | self.assertEqual(package.info.requiresVersion, "0.0")
46 | self.assertEqual(package.info.mainScript, "main.py")
47 |
48 | path = os.path.join(os.path.dirname(__file__), "package/simple.drawbot")
49 |
50 | package = DrawBotPackage(path)
51 | self.assertEqual(package.info.version, "1.0")
52 | self.assertEqual(package.info.developer, "drawbot")
53 | self.assertEqual(package.info.developerURL, "http://www.drawbot.com")
54 | self.assertEqual(package.info.requiresVersion, "3.0")
55 | self.assertEqual(package.info.mainScript, "main.py")
56 |
57 | def test_runPackages(self):
58 | path = os.path.join(os.path.dirname(__file__), "package/empty.drawbot")
59 |
60 | package = DrawBotPackage(path)
61 | with StdOutCollector() as output:
62 | succes, _ = package.run()
63 |
64 | self.assertEqual(output.lines(), ["hello world"])
65 |
66 | def test_missingMainScript(self):
67 | path = os.path.join(os.path.dirname(__file__), "package/missingMainScript.drawbot")
68 | package = DrawBotPackage(path)
69 | succes, message = package.run()
70 | self.assertEqual(succes, False)
71 | self.assertTrue(message.startswith("Cannot find"))
72 |
73 |
74 | if __name__ == "__main__":
75 | sys.exit(unittest.main())
76 |
--------------------------------------------------------------------------------