Compare commits
227 commits
ladyada-pa
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d28b6c6d1 | ||
|
|
59c9544605 | ||
|
|
f83687c47a | ||
|
|
61dac4d83d | ||
|
|
3f9ea73480 | ||
|
|
cf6d7130d0 | ||
|
|
ec28d2a8ec | ||
|
|
704744f417 | ||
|
|
1421c5d57e | ||
|
|
7d70ca7a7f | ||
|
|
518cc0c45d | ||
|
|
f37e66c2d3 | ||
|
|
5ff8c19af7 | ||
|
|
3b03903091 | ||
|
|
54acb53d11 | ||
|
|
6862809305 | ||
|
|
c30285993a | ||
|
|
5a514ce4ef | ||
|
|
a99517f50e | ||
|
|
62de33b401 | ||
|
|
11f7fe8b11 | ||
|
|
b598e15e79 | ||
|
|
ff4be2722d | ||
|
|
42579f870e | ||
|
|
d4517644f6 | ||
|
|
b0d1d5914a | ||
|
|
12440fd02a | ||
|
|
c16dac7dc2 | ||
|
|
b14b9455fd | ||
|
|
3084b17078 | ||
|
|
8c98dacd81 | ||
|
|
e443db2874 | ||
|
|
b6662efe48 | ||
|
|
e08643cdf8 | ||
|
|
61481a7182 | ||
|
|
dc3dcd2044 | ||
|
|
b66efa1323 | ||
|
|
e89c457f19 | ||
|
|
4cfc2a4675 | ||
|
|
6aac22d59d | ||
|
|
3c9e414c8a | ||
|
|
6a30b327dc | ||
|
|
119a7d0aed | ||
|
|
dfe6899570 | ||
|
|
4bdfb61e8d | ||
|
|
9ffd22a7b9 | ||
|
|
93756e43e6 | ||
|
|
9640d00d04 | ||
|
|
8a164973b6 | ||
|
|
accdb87056 | ||
|
|
ace3e7891f | ||
|
|
d0c7d38c56 | ||
|
|
25ff802a7c | ||
|
|
be6747308d | ||
|
|
4a7e7a017e | ||
|
|
b628dffa0e | ||
|
|
bf8577692c | ||
|
|
32f2bf2422 | ||
|
|
ab0158d623 | ||
|
|
d855e29c3e | ||
|
|
9fa93fe67d | ||
|
|
94e81582ea | ||
|
|
1649a68d60 | ||
|
|
bc70c46818 | ||
|
|
9b0fe91a6a | ||
|
|
dd13c494d7 | ||
|
|
85c9a7f4f6 | ||
|
|
fa74a7c121 | ||
|
|
bbc0ea9a68 | ||
|
|
48f2fb04b2 | ||
|
|
b3114027f3 | ||
|
|
f5195246cb | ||
|
|
a07b79fa45 | ||
|
|
ec98a7f54a | ||
|
|
b6ec018298 | ||
|
|
c2e3a79dc9 | ||
|
|
05affa4097 | ||
|
|
f106d483a1 | ||
|
|
c5af1119d9 | ||
|
|
aa4d0a0036 | ||
|
|
2063412f78 | ||
|
|
fdd5bd8894 | ||
|
|
51e13b2e61 | ||
|
|
2d65dc0f5c | ||
|
|
631d0447b3 | ||
|
|
062b1bc747 | ||
|
|
0b524cfe2b | ||
|
|
11b6fcbbe2 | ||
|
|
c9309dae6a | ||
|
|
2caeb592cc | ||
|
|
646b46d405 | ||
|
|
225b0b176a | ||
|
|
d020baba0f | ||
|
|
1dcecb9979 | ||
|
|
5fe2117df3 | ||
|
|
f5288fc8b5 | ||
|
|
0e42a2ddda | ||
|
|
d9ac04ec61 | ||
|
|
819eb1dda5 | ||
|
|
8661ce1f35 | ||
|
|
207cbc610c | ||
|
|
27411f5d09 | ||
|
|
cb5e370df4 | ||
|
|
d9f759eb43 | ||
|
|
1f2bf53313 | ||
|
|
05bd0ad842 | ||
|
|
93130c4da3 | ||
|
|
1be4aa3473 | ||
|
|
2efbd77edd | ||
|
|
f8c69dbe6b | ||
|
|
dcd466207c | ||
|
|
b49ec93f37 | ||
|
|
a1714217d2 | ||
|
|
9f4c2df9b2 | ||
|
|
a52eede646 | ||
|
|
c6951dcb69 | ||
|
|
04ba5b35b3 | ||
|
|
a90c00e4ac | ||
|
|
5c11366c86 | ||
|
|
ae577587e4 | ||
|
|
ee5a5ab408 | ||
|
|
7464d08d45 | ||
|
|
c41ca13f0a | ||
|
|
a51392c727 | ||
|
|
30e5a24edd | ||
|
|
b536f4fad9 | ||
|
|
fb0cfee6cc | ||
|
|
a392523a38 | ||
|
|
463fc685c4 | ||
|
|
387d67e25f | ||
|
|
713692a889 | ||
|
|
ec7b69ac69 | ||
|
|
a2cec0b8d9 | ||
|
|
e191c8a0e0 | ||
|
|
6695e3c7c4 | ||
|
|
a102ba2125 | ||
|
|
68c9522a34 | ||
|
|
83f43decae | ||
|
|
ac63a182ec | ||
|
|
173d0c5b67 | ||
|
|
ed64879d2d | ||
|
|
0defe7dea3 | ||
|
|
1c19264523 | ||
|
|
4acafa4b4f | ||
|
|
69cc1bf893 | ||
|
|
02f26d93e0 | ||
|
|
12d8b25f94 | ||
|
|
995f3decba | ||
|
|
e60fb65c70 | ||
|
|
a1c4859ca7 | ||
|
|
96f2f11555 | ||
|
|
52a3becd77 | ||
|
|
a2473b518e | ||
|
|
b5593bc5e5 | ||
|
|
b0ca00ef2f | ||
|
|
37febaef3c | ||
|
|
bb79810529 | ||
|
|
756088bbfc | ||
|
|
9a73454013 | ||
|
|
f26a881300 | ||
|
|
f91b78daa6 | ||
|
|
25c5a1aaba | ||
|
|
b45453a3ca | ||
|
|
ec69e74f9b | ||
|
|
ab57157574 | ||
|
|
c63451352f | ||
|
|
67d1fb32f5 | ||
|
|
81e07aadc4 | ||
|
|
83f581d752 | ||
|
|
f27dd3174e | ||
|
|
19183b701c | ||
|
|
509f9569b0 | ||
|
|
55a495e864 | ||
|
|
b506a0af03 | ||
|
|
72c5b627b9 | ||
|
|
4d65e55273 | ||
|
|
0fe25b5307 | ||
|
|
870643ae4e | ||
|
|
46b04fea72 | ||
|
|
80ebaa9b0d | ||
|
|
5dfc291763 | ||
|
|
fb70ae4b70 | ||
|
|
7868b40ae4 | ||
|
|
eae4cb4f48 | ||
|
|
39431ec92d | ||
|
|
cefd4545f5 | ||
|
|
2086944a56 | ||
|
|
3fa0b2c695 | ||
|
|
0d8bc6377c | ||
|
|
89ce1010af | ||
|
|
d84df43673 | ||
|
|
142054af67 | ||
|
|
36e199ac74 | ||
|
|
45d124932f | ||
|
|
193f6b5169 | ||
|
|
8ca3c1a724 | ||
|
|
afeb2a2669 | ||
|
|
4d53a379ab | ||
|
|
86130b39f2 | ||
|
|
344775b34a | ||
|
|
7c74bcd8ad | ||
|
|
12b47af9c2 | ||
|
|
2fdd09b0ff | ||
|
|
3c1734bb97 | ||
|
|
06bec73c12 | ||
|
|
85a0c6566f | ||
|
|
09bd2439bb | ||
|
|
da9710781c | ||
|
|
ac195417fc | ||
|
|
5583c493ce | ||
|
|
8bd76d98c7 | ||
|
|
a12762d7b6 | ||
|
|
1bbd0b8d4e | ||
|
|
5076127411 | ||
|
|
a507e09991 | ||
|
|
dce386c9c3 | ||
|
|
9ce37d2ced | ||
|
|
c2693bc02a | ||
|
|
56f474b2c5 | ||
|
|
1b0e3eb1da | ||
|
|
13323a09f9 | ||
|
|
ea45562020 | ||
|
|
2cc1ccb842 | ||
|
|
836918575b | ||
|
|
a23e5ff8b5 | ||
|
|
5ec1c88226 | ||
|
|
f297762fe0 |
21 changed files with 5801 additions and 201 deletions
57
.github/workflows/build.yml
vendored
Normal file
57
.github/workflows/build.yml
vendored
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
name: Build CI
|
||||
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- name: Translate Repo Name For Build Tools filename_prefix
|
||||
id: repo-name
|
||||
run: |
|
||||
echo ::set-output name=repo-name::$(
|
||||
echo ${{ github.repository }} |
|
||||
awk -F '\/' '{ print tolower($2) }' |
|
||||
tr '_' '-'
|
||||
)
|
||||
- name: Set up Python 3.6
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.6
|
||||
- name: Versions
|
||||
run: |
|
||||
python3 --version
|
||||
- name: Checkout Current Repo
|
||||
uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Checkout tools repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: adafruit/actions-ci-circuitpython-libs
|
||||
path: actions-ci
|
||||
- name: Install dependencies
|
||||
# (e.g. - apt-get: gettext, etc; pip: circuitpython-build-tools, requirements.txt; etc.)
|
||||
run: |
|
||||
source actions-ci/install.sh
|
||||
- name: Pip install pylint, black, & Sphinx
|
||||
run: |
|
||||
pip install --force-reinstall pylint black==19.10b0 Sphinx sphinx-rtd-theme
|
||||
- name: Library version
|
||||
run: git describe --dirty --always --tags
|
||||
- name: Check formatting
|
||||
run: |
|
||||
black --check --target-version=py35 .
|
||||
- name: PyLint
|
||||
run: |
|
||||
pylint $( find . -path './adafruit*.py' )
|
||||
([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace $( find . -path "./examples/*.py" ))
|
||||
- name: Build assets
|
||||
run: circuitpython-build-bundles --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location .
|
||||
- name: Build docs
|
||||
working-directory: docs
|
||||
run: sphinx-build -E -W -b html . _build/html
|
||||
81
.github/workflows/release.yml
vendored
Normal file
81
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
name: Release Actions
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
upload-release-assets:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dump GitHub context
|
||||
env:
|
||||
GITHUB_CONTEXT: ${{ toJson(github) }}
|
||||
run: echo "$GITHUB_CONTEXT"
|
||||
- name: Translate Repo Name For Build Tools filename_prefix
|
||||
id: repo-name
|
||||
run: |
|
||||
echo ::set-output name=repo-name::$(
|
||||
echo ${{ github.repository }} |
|
||||
awk -F '\/' '{ print tolower($2) }' |
|
||||
tr '_' '-'
|
||||
)
|
||||
- name: Set up Python 3.6
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.6
|
||||
- name: Versions
|
||||
run: |
|
||||
python3 --version
|
||||
- name: Checkout Current Repo
|
||||
uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: true
|
||||
- name: Checkout tools repo
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: adafruit/actions-ci-circuitpython-libs
|
||||
path: actions-ci
|
||||
- name: Install deps
|
||||
run: |
|
||||
source actions-ci/install.sh
|
||||
- name: Build assets
|
||||
run: circuitpython-build-bundles --filename_prefix ${{ steps.repo-name.outputs.repo-name }} --library_location .
|
||||
- name: Upload Release Assets
|
||||
# the 'official' actions version does not yet support dynamically
|
||||
# supplying asset names to upload. @csexton's version chosen based on
|
||||
# discussion in the issue below, as its the simplest to implement and
|
||||
# allows for selecting files with a pattern.
|
||||
# https://github.com/actions/upload-release-asset/issues/4
|
||||
#uses: actions/upload-release-asset@v1.0.1
|
||||
uses: csexton/release-asset-action@master
|
||||
with:
|
||||
pattern: "bundles/*"
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
upload-pypi:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Check For setup.py
|
||||
id: need-pypi
|
||||
run: |
|
||||
echo ::set-output name=setup-py::$( find . -wholename './setup.py' )
|
||||
- name: Set up Python
|
||||
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Install dependencies
|
||||
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install setuptools wheel twine
|
||||
- name: Build and publish
|
||||
if: contains(steps.need-pypi.outputs.setup-py, 'setup.py')
|
||||
env:
|
||||
TWINE_USERNAME: ${{ secrets.pypi_username }}
|
||||
TWINE_PASSWORD: ${{ secrets.pypi_password }}
|
||||
run: |
|
||||
python setup.py sdist
|
||||
twine upload dist/*
|
||||
7
.gitignore
vendored
7
.gitignore
vendored
|
|
@ -1,6 +1,11 @@
|
|||
*.mpy
|
||||
.idea
|
||||
__pycache__
|
||||
_build
|
||||
*.pyc
|
||||
.env
|
||||
build*
|
||||
bundles
|
||||
*.DS_Store
|
||||
.eggs
|
||||
dist
|
||||
**/*.egg-info
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ confidence=
|
|||
# no Warning level messages displayed, use"--disable=all --enable=classes
|
||||
# --disable=W"
|
||||
# disable=import-error,print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call
|
||||
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error
|
||||
disable=print-statement,parameter-unpacking,unpacking-in-except,old-raise-syntax,backtick,long-suffix,old-ne-operator,old-octal-literal,import-star-module-level,raw-checker-failed,bad-inline-option,locally-disabled,locally-enabled,file-ignored,suppressed-message,useless-suppression,deprecated-pragma,apply-builtin,basestring-builtin,buffer-builtin,cmp-builtin,coerce-builtin,execfile-builtin,file-builtin,long-builtin,raw_input-builtin,reduce-builtin,standarderror-builtin,unicode-builtin,xrange-builtin,coerce-method,delslice-method,getslice-method,setslice-method,no-absolute-import,old-division,dict-iter-method,dict-view-method,next-method-called,metaclass-assignment,indexing-exception,raising-string,reload-builtin,oct-method,hex-method,nonzero-method,cmp-method,input-builtin,round-builtin,intern-builtin,unichr-builtin,map-builtin-not-iterating,zip-builtin-not-iterating,range-builtin-not-iterating,filter-builtin-not-iterating,using-cmp-argument,eq-without-hash,div-method,idiv-method,rdiv-method,exception-message-attribute,invalid-str-codec,sys-max-int,bad-python3-import,deprecated-string-function,deprecated-str-translate-call,import-error,bad-continuation
|
||||
|
||||
# Enable the message, report, category or checker with the given id(s). You can
|
||||
# either give multiple identifier separated by comma (,) or put this option
|
||||
|
|
|
|||
39
.travis.yml
39
.travis.yml
|
|
@ -1,39 +0,0 @@
|
|||
# This is a common .travis.yml for generating library release zip files for
|
||||
# CircuitPython library releases using circuitpython-build-tools.
|
||||
# See https://github.com/adafruit/circuitpython-build-tools for detailed setup
|
||||
# instructions.
|
||||
|
||||
dist: xenial
|
||||
language: python
|
||||
python:
|
||||
- "3.6"
|
||||
|
||||
cache:
|
||||
pip: true
|
||||
|
||||
deploy:
|
||||
- provider: releases
|
||||
api_key: "$GITHUB_TOKEN"
|
||||
file_glob: true
|
||||
file: "$TRAVIS_BUILD_DIR/bundles/*"
|
||||
skip_cleanup: true
|
||||
overwrite: true
|
||||
on:
|
||||
tags: true
|
||||
- provider: pypi
|
||||
user: adafruit-travis
|
||||
password:
|
||||
secure: "P8vHzlHSkY7aLsGMD12+43hG4eHcxjqFWaKYhvtoUlbTjOtHD+ZlzFG8rSXooUEdJZWYy9SDFShGfNMvws1I5opNFV0HA2Cs14jBeYa9hFi0p/7Box0tAHZbi6aGGcho/WbwQqUgaOkH0QJnsYgZedu65S1SXVkl7zfcORMRw3dXBM5UY5Q7KP8X/62CC78P1dPC/2127vyn98qHVEiT7rtCkBgXUM3WuPz2VadaLodvAD/E0xwqJXqZmDIM2stc223m9n9plXPahUHl9grT9oH8KhJP9Wr6uaRjAOhbFKimKFWTEcc1ugHjH8U+UFRk+OVTDNf5etgiQMs82x2Ssfoz+yi6z/HMQN2uc9TM4kAGrPUZIcZTVaniCtGSfa7HZSj60uxDkTMKuOt5B+ey5bGjpRAsNxTRJtgT8taIWURO4YU9Il3orPr9ByIp1OqjRmHwGF0PXK+U5G6UEP+JP9R8OvS9Q71nOrDZmFAD0krw9ZxO4p4T93bgV4ELkoI8RLbudqh68FG6XYwg2hr+VPT/9eLuYeOGdHB7vNAc1qumOX+e3bbC0BdpexxYyBtgaWsbGZEP9F2uYi20wUWGnM1agFXpua1JiWAqKf14ML5ysOTsyWKJ8+IXNtQIyY9z9gD5TCiNgkyiHbDEg2JA2ATOuWz42UzhdxntXBCuV00="
|
||||
on:
|
||||
tags: true
|
||||
|
||||
install:
|
||||
- pip install -r requirements.txt
|
||||
- pip install circuitpython-build-tools Sphinx sphinx-rtd-theme
|
||||
- pip install --force-reinstall pylint==1.9.2
|
||||
|
||||
script:
|
||||
- pylint adafruit_display_text/*.py
|
||||
- ([[ ! -d "examples" ]] || pylint --disable=missing-docstring,invalid-name,bad-whitespace examples/*.py)
|
||||
- circuitpython-build-bundles --filename_prefix adafruit-circuitpython-display_text --library_location .
|
||||
- cd docs && sphinx-build -E -W -b html . _build/html && cd ..
|
||||
|
|
@ -34,6 +34,8 @@ Examples of unacceptable behavior by participants include:
|
|||
* Excessive or unwelcome helping; answering outside the scope of the question
|
||||
asked
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Promoting or spreading disinformation, lies, or conspiracy theories against
|
||||
a person, group, organisation, project, or community
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
|
|
@ -72,10 +74,10 @@ You may report in the following ways:
|
|||
In any situation, you may send an email to <support@adafruit.com>.
|
||||
|
||||
On the Adafruit Discord, you may send an open message from any channel
|
||||
to all Community Helpers by tagging @community helpers. You may also send an
|
||||
open message from any channel, or a direct message to @kattni#1507,
|
||||
@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or
|
||||
@Andon#8175.
|
||||
to all Community Moderators by tagging @community moderators. You may
|
||||
also send an open message from any channel, or a direct message to
|
||||
@kattni#1507, @tannewt#4653, @Dan Halbert#1614, @cater#2442,
|
||||
@sommersoft#0222, @Mr. Certainly#0472 or @Andon#8175.
|
||||
|
||||
Email and direct message reports will be kept confidential.
|
||||
|
||||
|
|
|
|||
33
README.rst
33
README.rst
|
|
@ -6,11 +6,11 @@ Introduction
|
|||
:alt: Documentation Status
|
||||
|
||||
.. image:: https://img.shields.io/discord/327254708534116352.svg
|
||||
:target: https://discord.gg/nBQh6qu
|
||||
:target: https://adafru.it/discord
|
||||
:alt: Discord
|
||||
|
||||
.. image:: https://travis-ci.com/adafruit/Adafruit_CircuitPython_Display_Text.svg?branch=master
|
||||
:target: https://travis-ci.com/adafruit/Adafruit_CircuitPython_Display_Text
|
||||
.. image:: https://github.com/adafruit/Adafruit_CircuitPython_Display_Text/workflows/Build%20CI/badge.svg
|
||||
:target: https://github.com/adafruit/Adafruit_CircuitPython_Display_Text/actions/
|
||||
:alt: Build Status
|
||||
|
||||
Displays text using CircuitPython's displayio.
|
||||
|
|
@ -36,11 +36,14 @@ For a board with a built-in display.
|
|||
import terminalio
|
||||
from adafruit_display_text import label
|
||||
|
||||
|
||||
text = "Hello world"
|
||||
text_area = label.Label(terminalio.FONT, text=text)
|
||||
text_area.x = 10
|
||||
text_area.y = 10
|
||||
board.DISPLAY.show(text_area)
|
||||
while True:
|
||||
pass
|
||||
|
||||
|
||||
Contributing
|
||||
|
|
@ -51,25 +54,7 @@ Contributions are welcome! Please read our `Code of Conduct
|
|||
before contributing to help this project stay welcoming.
|
||||
|
||||
|
||||
Sphinx documentation
|
||||
-----------------------
|
||||
Documentation
|
||||
=============
|
||||
|
||||
Sphinx is used to build the documentation based on rST files and comments in the code. First,
|
||||
install dependencies (feel free to reuse the virtual environment from above):
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
python3 -m venv .env
|
||||
source .env/bin/activate
|
||||
pip install Sphinx sphinx-rtd-theme
|
||||
|
||||
Now, once you have the virtual environment activated:
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
cd docs
|
||||
sphinx-build -E -W -b html . _build/html
|
||||
|
||||
This will output the documentation to ``docs/_build/html``. Open the index.html in your browser to
|
||||
view them. It will also (due to -W) error out on any warning like Travis will. This is a good way to
|
||||
locally verify it will pass.
|
||||
For information on building library documentation, please check out `this guide <https://learn.adafruit.com/creating-and-sharing-a-circuitpython-library/sharing-our-docs-on-readthedocs#sphinx-5-1>`_.
|
||||
|
|
|
|||
528
adafruit_display_text/bitmap_label.py
Executable file
528
adafruit_display_text/bitmap_label.py
Executable file
|
|
@ -0,0 +1,528 @@
|
|||
# The MIT License (MIT)
|
||||
#
|
||||
# Copyright (c) 2020 Kevin Matocha
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
"""
|
||||
`bitmap_label`
|
||||
================================================================================
|
||||
|
||||
Text graphics handling for CircuitPython, including text boxes
|
||||
|
||||
|
||||
* Author(s): Kevin Matocha
|
||||
|
||||
Implementation Notes
|
||||
--------------------
|
||||
|
||||
**Hardware:**
|
||||
|
||||
**Software and Dependencies:**
|
||||
|
||||
* Adafruit CircuitPython firmware for the supported boards:
|
||||
https://github.com/adafruit/circuitpython/releases
|
||||
|
||||
"""
|
||||
|
||||
import displayio
|
||||
|
||||
__version__ = "0.0.0-auto.0"
|
||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git"
|
||||
|
||||
|
||||
class Label(displayio.Group):
|
||||
"""A label displaying a string of text that is stored in a bitmap.
|
||||
Note: This ``bitmap_label.py`` library utilizes a bitmap to display the text.
|
||||
This method is memory-conserving relative to ``label.py``.
|
||||
For the bitmap_label library, the font, text, and line_spacing must be set at
|
||||
instancing and are immutable. The ``max_glyphs`` parameter is ignored and is present
|
||||
only for direct compatability with label.py.
|
||||
For use cases where text changes are required after the initial instancing, please
|
||||
use the `label.py` library.
|
||||
For further reduction in memory usage, set save_text to False (text string will not
|
||||
be stored).
|
||||
|
||||
The origin point set by ``x`` and ``y``
|
||||
properties will be the left edge of the bounding box, and in the center of a M
|
||||
glyph (if its one line), or the (number of lines * linespacing + M)/2. That is,
|
||||
it will try to have it be center-left as close as possible.
|
||||
|
||||
:param Font font: A font class that has ``get_bounding_box`` and ``get_glyph``.
|
||||
Must include a capital M for measuring character size.
|
||||
:param str text: Text to display
|
||||
:param int max_glyphs: Unnecessary parameter (provided only for direct compability
|
||||
with label.py)
|
||||
:param int color: Color of all text in RGB hex
|
||||
:param int background_color: Color of the background, use `None` for transparent
|
||||
:param double line_spacing: Line spacing of text to display
|
||||
:param boolean background_tight: Set `True` only if you want background box to tightly
|
||||
surround text
|
||||
:param int padding_top: Additional pixels added to background bounding box at top
|
||||
:param int padding_bottom: Additional pixels added to background bounding box at bottom
|
||||
:param int padding_left: Additional pixels added to background bounding box at left
|
||||
:param int padding_right: Additional pixels added to background bounding box at right
|
||||
:param (double,double) anchor_point: Point that anchored_position moves relative to.
|
||||
Tuple with decimal percentage of width and height.
|
||||
(E.g. (0,0) is top left, (1.0, 0.5): is middle right.)
|
||||
:param (int,int) anchored_position: Position relative to the anchor_point. Tuple
|
||||
containing x,y pixel coordinates.
|
||||
:param int scale: Integer value of the pixel scaling
|
||||
:param bool save_text: Set True to save the text string as a constant in the
|
||||
label structure. Set False to reduce memory use.
|
||||
"""
|
||||
|
||||
# pylint: disable=unused-argument, too-many-instance-attributes, too-many-locals, too-many-arguments
|
||||
# pylint: disable=too-many-branches, no-self-use
|
||||
# Note: max_glyphs parameter is unnecessary, this is used for direct
|
||||
# compatibility with label.py
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
font,
|
||||
x=0,
|
||||
y=0,
|
||||
text="",
|
||||
max_glyphs=None, # This input parameter is ignored, only present for compatibility
|
||||
# with label.py
|
||||
color=0xFFFFFF,
|
||||
background_color=None,
|
||||
line_spacing=1.25,
|
||||
background_tight=False,
|
||||
padding_top=0,
|
||||
padding_bottom=0,
|
||||
padding_left=0,
|
||||
padding_right=0,
|
||||
anchor_point=None,
|
||||
anchored_position=None,
|
||||
save_text=True, # can reduce memory use if save_text = False
|
||||
**kwargs
|
||||
):
|
||||
|
||||
if text == "":
|
||||
raise RuntimeError(
|
||||
"Please provide text string, or use label.py for mutable text"
|
||||
)
|
||||
|
||||
self._font = font
|
||||
|
||||
# Scale will be passed to Group using kwargs.
|
||||
if "scale" in kwargs.keys():
|
||||
self._scale = kwargs["scale"]
|
||||
else:
|
||||
self._scale = 1
|
||||
|
||||
self._line_spacing = line_spacing
|
||||
self._save_text = save_text
|
||||
|
||||
if self._save_text: # text string will be saved
|
||||
self._text = text
|
||||
else:
|
||||
self._text = None # save a None value since text string is not saved
|
||||
|
||||
# limit padding to >= 0
|
||||
padding_top = max(0, padding_top)
|
||||
padding_bottom = max(0, padding_bottom)
|
||||
padding_left = max(0, padding_left)
|
||||
padding_right = max(0, padding_right)
|
||||
|
||||
# Calculate the text bounding box
|
||||
|
||||
# Calculate tight box to provide bounding box dimensions to match label for
|
||||
# anchor_position calculations
|
||||
(
|
||||
tight_box_x,
|
||||
tight_box_y,
|
||||
tight_x_offset,
|
||||
tight_y_offset,
|
||||
) = self._text_bounding_box(
|
||||
text, font, self._line_spacing, background_tight=True,
|
||||
)
|
||||
|
||||
if background_tight:
|
||||
box_x = tight_box_x
|
||||
box_y = tight_box_y
|
||||
y_offset = tight_y_offset
|
||||
x_offset = tight_x_offset
|
||||
|
||||
else:
|
||||
(box_x, box_y, x_offset, y_offset) = self._text_bounding_box(
|
||||
text, font, self._line_spacing, background_tight=background_tight,
|
||||
)
|
||||
# Calculate the background size including padding
|
||||
box_x = box_x + padding_left + padding_right
|
||||
box_y = box_y + padding_top + padding_bottom
|
||||
|
||||
# Create the two-color palette
|
||||
self.palette = displayio.Palette(2)
|
||||
|
||||
self.background_color = background_color
|
||||
self.color = color
|
||||
|
||||
# Create the bitmap and TileGrid
|
||||
self.bitmap = displayio.Bitmap(box_x, box_y, len(self.palette))
|
||||
|
||||
# Place the text into the Bitmap
|
||||
self._place_text(
|
||||
self.bitmap,
|
||||
text,
|
||||
font,
|
||||
self._line_spacing,
|
||||
padding_left - x_offset,
|
||||
padding_top + y_offset,
|
||||
)
|
||||
|
||||
label_position_yoffset = int( # To calibrate with label.py positioning
|
||||
(font.get_glyph(ord("M")).height) / 2
|
||||
)
|
||||
|
||||
self.tilegrid = displayio.TileGrid(
|
||||
self.bitmap,
|
||||
pixel_shader=self.palette,
|
||||
width=1,
|
||||
height=1,
|
||||
tile_width=box_x,
|
||||
tile_height=box_y,
|
||||
default_tile=0,
|
||||
x=-padding_left + x_offset,
|
||||
y=label_position_yoffset - y_offset - padding_top,
|
||||
)
|
||||
|
||||
# instance the Group
|
||||
# this Group will contain just one TileGrid with one contained bitmap
|
||||
super().__init__(
|
||||
max_size=1, x=x, y=y, **kwargs
|
||||
) # this will include any arguments, including scale
|
||||
self.append(self.tilegrid) # add the bitmap's tilegrid to the group
|
||||
|
||||
# Update bounding_box values. Note: To be consistent with label.py,
|
||||
# this is the bounding box for the text only, not including the background.
|
||||
|
||||
self._bounding_box = (
|
||||
self.tilegrid.x,
|
||||
self.tilegrid.y,
|
||||
tight_box_x,
|
||||
tight_box_y,
|
||||
)
|
||||
|
||||
self._anchored_position = anchored_position
|
||||
self.anchor_point = anchor_point
|
||||
self.anchored_position = (
|
||||
self._anchored_position
|
||||
) # sets anchored_position with setter after bitmap is created
|
||||
|
||||
@staticmethod
|
||||
def _line_spacing_ypixels(font, line_spacing):
|
||||
# Note: Scale is not implemented at this time, any scaling is pushed up to the Group level
|
||||
return_value = int(line_spacing * font.get_bounding_box()[1])
|
||||
return return_value
|
||||
|
||||
def _text_bounding_box(self, text, font, line_spacing, background_tight=False):
|
||||
|
||||
# This empirical approach checks several glyphs for maximum ascender and descender height
|
||||
# (consistent with label.py)
|
||||
glyphs = "M j'" # choose glyphs with highest ascender and lowest
|
||||
# descender, will depend upon font used
|
||||
|
||||
try:
|
||||
self._font.load_glyphs(text + glyphs)
|
||||
except AttributeError:
|
||||
# ignore if font does not have load_glyphs
|
||||
pass
|
||||
|
||||
ascender_max = descender_max = 0
|
||||
for char in glyphs:
|
||||
this_glyph = font.get_glyph(ord(char))
|
||||
if this_glyph:
|
||||
ascender_max = max(ascender_max, this_glyph.height + this_glyph.dy)
|
||||
descender_max = max(descender_max, -this_glyph.dy)
|
||||
|
||||
lines = 1
|
||||
|
||||
xposition = (
|
||||
x_start
|
||||
) = yposition = y_start = 0 # starting x and y position (left margin)
|
||||
|
||||
left = None
|
||||
right = x_start
|
||||
top = bottom = y_start
|
||||
|
||||
y_offset_tight = int((font.get_glyph(ord("M")).height) / 2)
|
||||
# this needs to be reviewed (also in label.py), since it doesn't respond
|
||||
# properly to the number of newlines.
|
||||
|
||||
newline = False
|
||||
|
||||
for char in text:
|
||||
|
||||
if char == "\n": # newline
|
||||
newline = True
|
||||
|
||||
else:
|
||||
|
||||
my_glyph = font.get_glyph(ord(char))
|
||||
|
||||
if my_glyph is None: # Error checking: no glyph found
|
||||
print("Glyph not found: {}".format(repr(char)))
|
||||
else:
|
||||
if newline:
|
||||
newline = False
|
||||
xposition = x_start # reset to left column
|
||||
yposition = yposition + self._line_spacing_ypixels(
|
||||
font, line_spacing
|
||||
) # Add a newline
|
||||
lines += 1
|
||||
if xposition == x_start:
|
||||
if left is None:
|
||||
left = my_glyph.dx
|
||||
else:
|
||||
left = min(left, my_glyph.dx)
|
||||
xright = xposition + my_glyph.width + my_glyph.dx
|
||||
xposition += my_glyph.shift_x
|
||||
|
||||
right = max(right, xposition, xright)
|
||||
|
||||
if yposition == y_start: # first line, find the Ascender height
|
||||
top = min(top, -my_glyph.height - my_glyph.dy + y_offset_tight)
|
||||
bottom = max(bottom, yposition - my_glyph.dy + y_offset_tight)
|
||||
|
||||
if left is None:
|
||||
left = 0
|
||||
|
||||
final_box_width = right - left
|
||||
if background_tight:
|
||||
final_box_height = bottom - top
|
||||
final_y_offset = -top + y_offset_tight
|
||||
|
||||
else:
|
||||
final_box_height = (lines - 1) * self._line_spacing_ypixels(
|
||||
font, line_spacing
|
||||
) + (ascender_max + descender_max)
|
||||
final_y_offset = ascender_max
|
||||
|
||||
return (final_box_width, final_box_height, left, final_y_offset)
|
||||
|
||||
# pylint: disable=too-many-nested-blocks
|
||||
def _place_text(
|
||||
self,
|
||||
bitmap,
|
||||
text,
|
||||
font,
|
||||
line_spacing,
|
||||
xposition,
|
||||
yposition,
|
||||
text_palette_index=1,
|
||||
background_palette_index=0,
|
||||
print_only_pixels=True, # print_only_pixels = True: only update the bitmap where the glyph
|
||||
# pixel color is > 0. This is especially useful for script fonts where glyph
|
||||
# bounding boxes overlap
|
||||
# Set `print_only_pixels=False` to write all pixels
|
||||
):
|
||||
# placeText - Writes text into a bitmap at the specified location.
|
||||
#
|
||||
# Verify paletteIndex is working properly with * operator, especially
|
||||
# if accommodating multicolored fonts
|
||||
#
|
||||
# Note: Scale is not implemented at this time, is pushed up to Group level
|
||||
|
||||
bitmap_width = bitmap.width
|
||||
bitmap_height = bitmap.height
|
||||
|
||||
x_start = xposition # starting x position (left margin)
|
||||
y_start = yposition
|
||||
|
||||
left = None
|
||||
right = x_start
|
||||
top = bottom = y_start
|
||||
|
||||
for char in text:
|
||||
|
||||
if char == "\n": # newline
|
||||
xposition = x_start # reset to left column
|
||||
yposition = yposition + self._line_spacing_ypixels(
|
||||
font, line_spacing
|
||||
) # Add a newline
|
||||
|
||||
else:
|
||||
|
||||
my_glyph = font.get_glyph(ord(char))
|
||||
|
||||
if my_glyph is None: # Error checking: no glyph found
|
||||
print("Glyph not found: {}".format(repr(char)))
|
||||
else:
|
||||
if xposition == x_start:
|
||||
if left is None:
|
||||
left = my_glyph.dx
|
||||
else:
|
||||
left = min(left, my_glyph.dx)
|
||||
|
||||
right = max(
|
||||
right,
|
||||
xposition + my_glyph.shift_x,
|
||||
xposition + my_glyph.width + my_glyph.dx,
|
||||
)
|
||||
if yposition == y_start: # first line, find the Ascender height
|
||||
top = min(top, -my_glyph.height - my_glyph.dy)
|
||||
bottom = max(bottom, yposition - my_glyph.dy)
|
||||
|
||||
glyph_offset_x = (
|
||||
my_glyph.tile_index * my_glyph.width
|
||||
) # for type BuiltinFont, this creates the x-offset in the glyph bitmap.
|
||||
# for BDF loaded fonts, this should equal 0
|
||||
|
||||
for y in range(my_glyph.height):
|
||||
for x in range(my_glyph.width):
|
||||
x_placement = x + xposition + my_glyph.dx
|
||||
y_placement = y + yposition - my_glyph.height - my_glyph.dy
|
||||
|
||||
if (bitmap_width > x_placement >= 0) and (
|
||||
bitmap_height > y_placement >= 0
|
||||
):
|
||||
|
||||
# Allows for remapping the bitmap indexes using paletteIndex
|
||||
# for background and text.
|
||||
palette_indexes = (
|
||||
background_palette_index,
|
||||
text_palette_index,
|
||||
)
|
||||
|
||||
this_pixel_color = palette_indexes[
|
||||
my_glyph.bitmap[
|
||||
y * my_glyph.bitmap.width + x + glyph_offset_x
|
||||
]
|
||||
]
|
||||
|
||||
if not print_only_pixels or this_pixel_color > 0:
|
||||
# write all characters if printOnlyPixels = False,
|
||||
# or if thisPixelColor is > 0
|
||||
bitmap[
|
||||
y_placement * bitmap_width + x_placement
|
||||
] = this_pixel_color
|
||||
elif y_placement > bitmap_height:
|
||||
break
|
||||
|
||||
xposition = xposition + my_glyph.shift_x
|
||||
|
||||
return (left, top, right - left, bottom - top) # bounding_box
|
||||
|
||||
@property
|
||||
def bounding_box(self):
|
||||
"""An (x, y, w, h) tuple that completely covers all glyphs. The
|
||||
first two numbers are offset from the x, y origin of this group"""
|
||||
return self._bounding_box
|
||||
|
||||
@property
|
||||
def line_spacing(self):
|
||||
"""The amount of space between lines of text, in multiples of the font's
|
||||
bounding-box height. (E.g. 1.0 is the bounding-box height)"""
|
||||
return self._line_spacing
|
||||
|
||||
@line_spacing.setter
|
||||
def line_spacing(self, new_line_spacing):
|
||||
raise RuntimeError(
|
||||
"line_spacing is immutable for bitmap_label.py; use label.py for mutable line_spacing"
|
||||
)
|
||||
|
||||
@property
|
||||
def color(self):
|
||||
"""Color of the text as an RGB hex number."""
|
||||
return self._color
|
||||
|
||||
@color.setter
|
||||
def color(self, new_color):
|
||||
self._color = new_color
|
||||
if new_color is not None:
|
||||
self.palette[1] = new_color
|
||||
self.palette.make_opaque(1)
|
||||
else:
|
||||
self.palette[1] = 0
|
||||
self.palette.make_transparent(1)
|
||||
|
||||
@property
|
||||
def background_color(self):
|
||||
"""Color of the background as an RGB hex number."""
|
||||
return self._background_color
|
||||
|
||||
@background_color.setter
|
||||
def background_color(self, new_color):
|
||||
self._background_color = new_color
|
||||
if new_color is not None:
|
||||
self.palette[0] = new_color
|
||||
self.palette.make_opaque(0)
|
||||
else:
|
||||
self.palette[0] = 0
|
||||
self.palette.make_transparent(0)
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
"""Text to displayed."""
|
||||
return self._text
|
||||
|
||||
@text.setter
|
||||
def text(self, new_text):
|
||||
raise RuntimeError(
|
||||
"text is immutable for bitmap_label.py; use label.py library for mutable text"
|
||||
)
|
||||
|
||||
@property
|
||||
def font(self):
|
||||
"""Font to use for text display."""
|
||||
return self.font
|
||||
|
||||
@font.setter
|
||||
def font(self, new_font):
|
||||
raise RuntimeError(
|
||||
"font is immutable for bitmap_label.py; use label.py library for mutable font"
|
||||
)
|
||||
|
||||
@property
|
||||
def anchor_point(self):
|
||||
"""Point that anchored_position moves relative to.
|
||||
Tuple with decimal percentage of width and height.
|
||||
(E.g. (0,0) is top left, (1.0, 0.5): is middle right.)"""
|
||||
return self._anchor_point
|
||||
|
||||
@anchor_point.setter
|
||||
def anchor_point(self, new_anchor_point):
|
||||
self._anchor_point = new_anchor_point
|
||||
self.anchored_position = (
|
||||
self._anchored_position
|
||||
) # update the anchored_position using setter
|
||||
|
||||
@property
|
||||
def anchored_position(self):
|
||||
"""Position relative to the anchor_point. Tuple containing x,y
|
||||
pixel coordinates."""
|
||||
return self._anchored_position
|
||||
|
||||
@anchored_position.setter
|
||||
def anchored_position(self, new_position):
|
||||
self._anchored_position = new_position
|
||||
|
||||
# Set anchored_position
|
||||
if (self._anchor_point is not None) and (self._anchored_position is not None):
|
||||
self.x = int(
|
||||
new_position[0]
|
||||
- (self._bounding_box[0] * self._scale)
|
||||
- round(self._anchor_point[0] * (self._bounding_box[2] * self._scale))
|
||||
)
|
||||
self.y = int(
|
||||
new_position[1]
|
||||
- (self._bounding_box[1] * self._scale)
|
||||
- round(self._anchor_point[1] * self._bounding_box[3] * self._scale)
|
||||
)
|
||||
350
adafruit_display_text/label.py
Normal file → Executable file
350
adafruit_display_text/label.py
Normal file → Executable file
|
|
@ -44,100 +44,265 @@ import displayio
|
|||
__version__ = "0.0.0-auto.0"
|
||||
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git"
|
||||
|
||||
|
||||
class Label(displayio.Group):
|
||||
"""A label displaying a string of text. The origin point set by ``x`` and ``y``
|
||||
properties will be the left edge of the bounding box, and in the center of a M
|
||||
glyph (if its one line), or the (number of lines * linespacing + M)/2. That is,
|
||||
it will try to have it be center-left as close as possible.
|
||||
|
||||
:param Font font: A font class that has ``get_bounding_box`` and ``get_glyph``
|
||||
:param Font font: A font class that has ``get_bounding_box`` and ``get_glyph``.
|
||||
Must include a capital M for measuring character size.
|
||||
:param str text: Text to display
|
||||
:param int max_glyphs: The largest quantity of glyphs we will display
|
||||
:param int color: Color of all text in RGB hex
|
||||
:param double line_spacing: Line spacing of text to display"""
|
||||
def __init__(self, font, *, text=None, max_glyphs=None, color=0xffffff,
|
||||
line_spacing=1.25, **kwargs):
|
||||
|
||||
# pylint: disable=too-many-instance-attributes, too-many-locals
|
||||
# This has a lot of getters/setters, maybe it needs cleanup.
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
font,
|
||||
*,
|
||||
x=0,
|
||||
y=0,
|
||||
text="",
|
||||
max_glyphs=None,
|
||||
color=0xFFFFFF,
|
||||
background_color=None,
|
||||
line_spacing=1.25,
|
||||
background_tight=False,
|
||||
padding_top=0,
|
||||
padding_bottom=0,
|
||||
padding_left=0,
|
||||
padding_right=0,
|
||||
anchor_point=None,
|
||||
anchored_position=None,
|
||||
**kwargs
|
||||
):
|
||||
if "scale" in kwargs.keys():
|
||||
self._scale = kwargs["scale"]
|
||||
else:
|
||||
self._scale = 1
|
||||
if not max_glyphs and not text:
|
||||
raise RuntimeError("Please provide a max size, or initial text")
|
||||
if not max_glyphs:
|
||||
max_glyphs = len(text)
|
||||
super().__init__(max_size=max_glyphs, **kwargs)
|
||||
# add one to max_size for the background bitmap tileGrid
|
||||
super().__init__(max_size=max_glyphs + 1, **kwargs)
|
||||
|
||||
self.width = max_glyphs
|
||||
self.font = font
|
||||
self._font = font
|
||||
self._text = None
|
||||
self._anchor_point = anchor_point
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
self.palette = displayio.Palette(2)
|
||||
self.palette.make_transparent(0)
|
||||
self.palette[1] = color
|
||||
|
||||
bounds = self.font.get_bounding_box()
|
||||
self.height = bounds[1]
|
||||
self.height = self._font.get_bounding_box()[1]
|
||||
self._line_spacing = line_spacing
|
||||
self._boundingbox = None
|
||||
|
||||
if text:
|
||||
self._update_text(text)
|
||||
self._background_tight = (
|
||||
background_tight # sets padding status for text background box
|
||||
)
|
||||
|
||||
# Create the two-color text palette
|
||||
self.palette = displayio.Palette(2)
|
||||
self.palette[0] = 0
|
||||
self.palette.make_transparent(0)
|
||||
self.color = color
|
||||
|
||||
def _update_text(self, new_text): # pylint: disable=too-many-locals
|
||||
self._background_color = background_color
|
||||
self._background_palette = displayio.Palette(1)
|
||||
self._added_background_tilegrid = False
|
||||
|
||||
self._padding_top = padding_top
|
||||
self._padding_bottom = padding_bottom
|
||||
self._padding_left = padding_left
|
||||
self._padding_right = padding_right
|
||||
|
||||
if text is not None:
|
||||
self._update_text(str(text))
|
||||
if (anchored_position is not None) and (anchor_point is not None):
|
||||
self.anchored_position = anchored_position
|
||||
|
||||
def _create_background_box(self, lines, y_offset):
|
||||
|
||||
left = self._boundingbox[0]
|
||||
|
||||
if self._background_tight: # draw a tight bounding box
|
||||
box_width = self._boundingbox[2]
|
||||
box_height = self._boundingbox[3]
|
||||
x_box_offset = 0
|
||||
y_box_offset = self._boundingbox[1]
|
||||
|
||||
else: # draw a "loose" bounding box to include any ascenders/descenders.
|
||||
|
||||
# check a few glyphs for maximum ascender and descender height
|
||||
# Enhancement: it would be preferred to access the font "FONT_ASCENT" and
|
||||
# "FONT_DESCENT" in the imported BDF file
|
||||
glyphs = "M j'" # choose glyphs with highest ascender and lowest
|
||||
# descender, will depend upon font used
|
||||
ascender_max = descender_max = 0
|
||||
for char in glyphs:
|
||||
this_glyph = self._font.get_glyph(ord(char))
|
||||
if this_glyph:
|
||||
ascender_max = max(ascender_max, this_glyph.height + this_glyph.dy)
|
||||
descender_max = max(descender_max, -this_glyph.dy)
|
||||
|
||||
box_width = self._boundingbox[2] + self._padding_left + self._padding_right
|
||||
x_box_offset = -self._padding_left
|
||||
box_height = (
|
||||
(ascender_max + descender_max)
|
||||
+ int((lines - 1) * self.height * self._line_spacing)
|
||||
+ self._padding_top
|
||||
+ self._padding_bottom
|
||||
)
|
||||
y_box_offset = -ascender_max + y_offset - self._padding_top
|
||||
|
||||
box_width = max(0, box_width) # remove any negative values
|
||||
box_height = max(0, box_height) # remove any negative values
|
||||
|
||||
background_bitmap = displayio.Bitmap(box_width, box_height, 1)
|
||||
tile_grid = displayio.TileGrid(
|
||||
background_bitmap,
|
||||
pixel_shader=self._background_palette,
|
||||
x=left + x_box_offset,
|
||||
y=y_box_offset,
|
||||
)
|
||||
|
||||
return tile_grid
|
||||
|
||||
def _update_background_color(self, new_color):
|
||||
|
||||
if new_color is None:
|
||||
self._background_palette.make_transparent(0)
|
||||
if self._added_background_tilegrid:
|
||||
self.pop(0)
|
||||
self._added_background_tilegrid = False
|
||||
else:
|
||||
self._background_palette.make_opaque(0)
|
||||
self._background_palette[0] = new_color
|
||||
self._background_color = new_color
|
||||
|
||||
lines = self._text.rstrip("\n").count("\n") + 1
|
||||
y_offset = int((self._font.get_glyph(ord("M")).height) / 2)
|
||||
|
||||
if not self._added_background_tilegrid: # no bitmap is in the self Group
|
||||
# add bitmap if text is present and bitmap sizes > 0 pixels
|
||||
if (
|
||||
(len(self._text) > 0)
|
||||
and (
|
||||
self._boundingbox[2] + self._padding_left + self._padding_right > 0
|
||||
)
|
||||
and (
|
||||
self._boundingbox[3] + self._padding_top + self._padding_bottom > 0
|
||||
)
|
||||
):
|
||||
if len(self) > 0:
|
||||
self.insert(0, self._create_background_box(lines, y_offset))
|
||||
else:
|
||||
self.append(self._create_background_box(lines, y_offset))
|
||||
self._added_background_tilegrid = True
|
||||
|
||||
else: # a bitmap is present in the self Group
|
||||
# update bitmap if text is present and bitmap sizes > 0 pixels
|
||||
if (
|
||||
(len(self._text) > 0)
|
||||
and (
|
||||
self._boundingbox[2] + self._padding_left + self._padding_right > 0
|
||||
)
|
||||
and (
|
||||
self._boundingbox[3] + self._padding_top + self._padding_bottom > 0
|
||||
)
|
||||
):
|
||||
self[0] = self._create_background_box(lines, y_offset)
|
||||
else: # delete the existing bitmap
|
||||
self.pop(0)
|
||||
self._added_background_tilegrid = False
|
||||
|
||||
def _update_text(
|
||||
self, new_text
|
||||
): # pylint: disable=too-many-locals ,too-many-branches, too-many-statements
|
||||
x = 0
|
||||
y = 0
|
||||
if self._added_background_tilegrid:
|
||||
i = 1
|
||||
else:
|
||||
i = 0
|
||||
old_c = 0
|
||||
y_offset = int((self.font.get_glyph(ord('M')).height -
|
||||
new_text.count('\n') * self.height * self.line_spacing) / 2)
|
||||
#print("y offset from baseline", y_offset)
|
||||
left = right = top = bottom = 0
|
||||
tilegrid_count = i
|
||||
|
||||
try:
|
||||
self._font.load_glyphs(new_text + "M")
|
||||
except AttributeError:
|
||||
# ignore if font does not have load_glyphs
|
||||
pass
|
||||
|
||||
y_offset = int((self._font.get_glyph(ord("M")).height) / 2)
|
||||
|
||||
right = top = bottom = 0
|
||||
left = None
|
||||
|
||||
for character in new_text:
|
||||
if character == '\n':
|
||||
if character == "\n":
|
||||
y += int(self.height * self._line_spacing)
|
||||
x = 0
|
||||
continue
|
||||
glyph = self.font.get_glyph(ord(character))
|
||||
glyph = self._font.get_glyph(ord(character))
|
||||
if not glyph:
|
||||
continue
|
||||
right = max(right, x+glyph.width)
|
||||
right = max(right, x + glyph.shift_x, x + glyph.width + glyph.dx)
|
||||
if x == 0:
|
||||
if left is None:
|
||||
left = glyph.dx
|
||||
else:
|
||||
left = min(left, glyph.dx)
|
||||
if y == 0: # first line, find the Ascender height
|
||||
top = min(top, -glyph.height+y_offset)
|
||||
bottom = max(bottom, y-glyph.dy+y_offset)
|
||||
top = min(top, -glyph.height - glyph.dy + y_offset)
|
||||
bottom = max(bottom, y - glyph.dy + y_offset)
|
||||
position_y = y - glyph.height - glyph.dy + y_offset
|
||||
position_x = x + glyph.dx
|
||||
if not self._text or old_c >= len(self._text) or character != self._text[old_c]:
|
||||
if glyph.width > 0 and glyph.height > 0:
|
||||
try:
|
||||
face = displayio.TileGrid(glyph.bitmap, pixel_shader=self.palette,
|
||||
# pylint: disable=unexpected-keyword-arg
|
||||
face = displayio.TileGrid(
|
||||
glyph.bitmap,
|
||||
pixel_shader=self.palette,
|
||||
default_tile=glyph.tile_index,
|
||||
tile_width=glyph.width, tile_height=glyph.height,
|
||||
position=(position_x, position_y))
|
||||
tile_width=glyph.width,
|
||||
tile_height=glyph.height,
|
||||
position=(position_x, position_y),
|
||||
)
|
||||
except TypeError:
|
||||
face = displayio.TileGrid(glyph.bitmap, pixel_shader=self.palette,
|
||||
face = displayio.TileGrid(
|
||||
glyph.bitmap,
|
||||
pixel_shader=self.palette,
|
||||
default_tile=glyph.tile_index,
|
||||
tile_width=glyph.width, tile_height=glyph.height,
|
||||
x=position_x, y=position_y)
|
||||
if i < len(self):
|
||||
self[i] = face
|
||||
tile_width=glyph.width,
|
||||
tile_height=glyph.height,
|
||||
x=position_x,
|
||||
y=position_y,
|
||||
)
|
||||
if tilegrid_count < len(self):
|
||||
self[tilegrid_count] = face
|
||||
else:
|
||||
self.append(face)
|
||||
elif self._text and character == self._text[old_c]:
|
||||
try:
|
||||
self[i].position = (position_x, position_y)
|
||||
except AttributeError:
|
||||
self[i].x = position_x
|
||||
self[i].y = position_y
|
||||
|
||||
tilegrid_count += 1
|
||||
x += glyph.shift_x
|
||||
|
||||
# TODO skip this for control sequences or non-printables.
|
||||
i += 1
|
||||
old_c += 1
|
||||
# skip all non-prinables in the old string
|
||||
while (self._text and old_c < len(self._text) and
|
||||
(self._text[old_c] == '\n' or not self.font.get_glyph(ord(self._text[old_c])))):
|
||||
old_c += 1
|
||||
# Remove the rest
|
||||
while len(self) > i:
|
||||
|
||||
if left is None:
|
||||
left = 0
|
||||
|
||||
while len(self) > tilegrid_count: # i:
|
||||
self.pop()
|
||||
self._text = new_text
|
||||
self._boundingbox = (left, top, left+right, bottom-top)
|
||||
self._boundingbox = (left, top, right - left, bottom - top)
|
||||
|
||||
if self.background_color is not None:
|
||||
self._update_background_color(self._background_color)
|
||||
|
||||
@property
|
||||
def bounding_box(self):
|
||||
|
|
@ -162,7 +327,22 @@ class Label(displayio.Group):
|
|||
|
||||
@color.setter
|
||||
def color(self, new_color):
|
||||
self._color = new_color
|
||||
if new_color is not None:
|
||||
self.palette[1] = new_color
|
||||
self.palette.make_opaque(1)
|
||||
else:
|
||||
self.palette[1] = 0
|
||||
self.palette.make_transparent(1)
|
||||
|
||||
@property
|
||||
def background_color(self):
|
||||
"""Color of the background as an RGB hex number."""
|
||||
return self._background_color
|
||||
|
||||
@background_color.setter
|
||||
def background_color(self, new_color):
|
||||
self._update_background_color(new_color)
|
||||
|
||||
@property
|
||||
def text(self):
|
||||
|
|
@ -171,4 +351,74 @@ class Label(displayio.Group):
|
|||
|
||||
@text.setter
|
||||
def text(self, new_text):
|
||||
self._update_text(new_text)
|
||||
try:
|
||||
current_anchored_position = self.anchored_position
|
||||
self._update_text(str(new_text))
|
||||
self.anchored_position = current_anchored_position
|
||||
except RuntimeError as run_error:
|
||||
raise RuntimeError("Text length exceeds max_glyphs") from run_error
|
||||
|
||||
@property
|
||||
def font(self):
|
||||
"""Font to use for text display."""
|
||||
return self._font
|
||||
|
||||
@font.setter
|
||||
def font(self, new_font):
|
||||
old_text = self._text
|
||||
current_anchored_position = self.anchored_position
|
||||
self._text = ""
|
||||
self._font = new_font
|
||||
self.height = self._font.get_bounding_box()[1]
|
||||
self._update_text(str(old_text))
|
||||
self.anchored_position = current_anchored_position
|
||||
|
||||
@property
|
||||
def anchor_point(self):
|
||||
"""Point that anchored_position moves relative to.
|
||||
Tuple with decimal percentage of width and height.
|
||||
(E.g. (0,0) is top left, (1.0, 0.5): is middle right.)"""
|
||||
return self._anchor_point
|
||||
|
||||
@anchor_point.setter
|
||||
def anchor_point(self, new_anchor_point):
|
||||
if self._anchor_point is not None:
|
||||
current_anchored_position = self.anchored_position
|
||||
self._anchor_point = new_anchor_point
|
||||
self.anchored_position = current_anchored_position
|
||||
else:
|
||||
self._anchor_point = new_anchor_point
|
||||
|
||||
@property
|
||||
def anchored_position(self):
|
||||
"""Position relative to the anchor_point. Tuple containing x,y
|
||||
pixel coordinates."""
|
||||
if self._anchor_point is None:
|
||||
return None
|
||||
return (
|
||||
int(
|
||||
self.x
|
||||
+ (self._boundingbox[0] * self._scale)
|
||||
+ round(self._anchor_point[0] * self._boundingbox[2] * self._scale)
|
||||
),
|
||||
int(
|
||||
self.y
|
||||
+ (self._boundingbox[1] * self._scale)
|
||||
+ round(self._anchor_point[1] * self._boundingbox[3] * self._scale)
|
||||
),
|
||||
)
|
||||
|
||||
@anchored_position.setter
|
||||
def anchored_position(self, new_position):
|
||||
if (self._anchor_point is None) or (new_position is None):
|
||||
return # Note: anchor_point must be set before setting anchored_position
|
||||
self.x = int(
|
||||
new_position[0]
|
||||
- (self._boundingbox[0] * self._scale)
|
||||
- round(self._anchor_point[0] * (self._boundingbox[2] * self._scale))
|
||||
)
|
||||
self.y = int(
|
||||
new_position[1]
|
||||
- (self._boundingbox[1] * self._scale)
|
||||
- round(self._anchor_point[1] * self._boundingbox[3] * self._scale)
|
||||
)
|
||||
|
|
|
|||
88
docs/conf.py
88
docs/conf.py
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
import os
|
||||
import sys
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
sys.path.insert(0, os.path.abspath(".."))
|
||||
|
||||
# -- General configuration ------------------------------------------------
|
||||
|
||||
|
|
@ -10,10 +11,10 @@ sys.path.insert(0, os.path.abspath('..'))
|
|||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
'sphinx.ext.intersphinx',
|
||||
'sphinx.ext.napoleon',
|
||||
'sphinx.ext.todo',
|
||||
"sphinx.ext.autodoc",
|
||||
"sphinx.ext.intersphinx",
|
||||
"sphinx.ext.napoleon",
|
||||
"sphinx.ext.todo",
|
||||
]
|
||||
|
||||
# TODO: Please Read!
|
||||
|
|
@ -23,29 +24,32 @@ extensions = [
|
|||
autodoc_mock_imports = ["displayio"]
|
||||
|
||||
|
||||
intersphinx_mapping = {'python': ('https://docs.python.org/3.4', None),'CircuitPython': ('https://circuitpython.readthedocs.io/en/latest/', None)}
|
||||
intersphinx_mapping = {
|
||||
"python": ("https://docs.python.org/3.4", None),
|
||||
"CircuitPython": ("https://circuitpython.readthedocs.io/en/latest/", None),
|
||||
}
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
templates_path = ["_templates"]
|
||||
|
||||
source_suffix = '.rst'
|
||||
source_suffix = ".rst"
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
master_doc = "index"
|
||||
|
||||
# General information about the project.
|
||||
project = u'Adafruit Display_Text Library'
|
||||
copyright = u'2019 Scott Shawcroft'
|
||||
author = u'Scott Shawcroft'
|
||||
project = "Adafruit Display_Text Library"
|
||||
copyright = "2019 Scott Shawcroft"
|
||||
author = "Scott Shawcroft"
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = u'1.0'
|
||||
version = "1.0"
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'1.0'
|
||||
release = "1.0"
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
|
@ -57,7 +61,7 @@ language = None
|
|||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This patterns also effect to html_static_path and html_extra_path
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', '.env', 'CODE_OF_CONDUCT.md']
|
||||
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", ".env", "CODE_OF_CONDUCT.md"]
|
||||
|
||||
# The reST default role (used for this markup: `text`) to use for all
|
||||
# documents.
|
||||
|
|
@ -69,7 +73,7 @@ default_role = "any"
|
|||
add_function_parentheses = True
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
pygments_style = "sphinx"
|
||||
|
||||
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||
todo_include_todos = False
|
||||
|
|
@ -84,32 +88,33 @@ napoleon_numpy_docstring = False
|
|||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
|
||||
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
|
||||
|
||||
if not on_rtd: # only import and set the theme if we're building docs locally
|
||||
try:
|
||||
import sphinx_rtd_theme
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), '.']
|
||||
|
||||
html_theme = "sphinx_rtd_theme"
|
||||
html_theme_path = [sphinx_rtd_theme.get_html_theme_path(), "."]
|
||||
except:
|
||||
html_theme = 'default'
|
||||
html_theme_path = ['.']
|
||||
html_theme = "default"
|
||||
html_theme_path = ["."]
|
||||
else:
|
||||
html_theme_path = ['.']
|
||||
html_theme_path = ["."]
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_static_path = ["_static"]
|
||||
|
||||
# The name of an image file (relative to this directory) to use as a favicon of
|
||||
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||
# pixels large.
|
||||
#
|
||||
html_favicon = '_static/favicon.ico'
|
||||
html_favicon = "_static/favicon.ico"
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = 'AdafruitDisplay_textLibrarydoc'
|
||||
htmlhelp_basename = "AdafruitDisplay_textLibrarydoc"
|
||||
|
||||
# -- Options for LaTeX output ---------------------------------------------
|
||||
|
||||
|
|
@ -117,15 +122,12 @@ latex_elements = {
|
|||
# The paper size ('letterpaper' or 'a4paper').
|
||||
#
|
||||
# 'papersize': 'letterpaper',
|
||||
|
||||
# The font size ('10pt', '11pt' or '12pt').
|
||||
#
|
||||
# 'pointsize': '10pt',
|
||||
|
||||
# Additional stuff for the LaTeX preamble.
|
||||
#
|
||||
# 'preamble': '',
|
||||
|
||||
# Latex figure (float) alignment
|
||||
#
|
||||
# 'figure_align': 'htbp',
|
||||
|
|
@ -135,8 +137,13 @@ latex_elements = {
|
|||
# (source start file, target name, title,
|
||||
# author, documentclass [howto, manual, or own class]).
|
||||
latex_documents = [
|
||||
(master_doc, 'AdafruitDisplay_TextLibrary.tex', u'AdafruitDisplay_Text Library Documentation',
|
||||
author, 'manual'),
|
||||
(
|
||||
master_doc,
|
||||
"AdafruitDisplay_TextLibrary.tex",
|
||||
"AdafruitDisplay_Text Library Documentation",
|
||||
author,
|
||||
"manual",
|
||||
),
|
||||
]
|
||||
|
||||
# -- Options for manual page output ---------------------------------------
|
||||
|
|
@ -144,8 +151,13 @@ latex_documents = [
|
|||
# One entry per manual page. List of tuples
|
||||
# (source start file, name, description, authors, manual section).
|
||||
man_pages = [
|
||||
(master_doc, 'AdafruitDisplay_Textlibrary', u'Adafruit Display_Text Library Documentation',
|
||||
[author], 1)
|
||||
(
|
||||
master_doc,
|
||||
"AdafruitDisplay_Textlibrary",
|
||||
"Adafruit Display_Text Library Documentation",
|
||||
[author],
|
||||
1,
|
||||
)
|
||||
]
|
||||
|
||||
# -- Options for Texinfo output -------------------------------------------
|
||||
|
|
@ -154,7 +166,13 @@ man_pages = [
|
|||
# (source start file, target name, title, author,
|
||||
# dir menu entry, description, category)
|
||||
texinfo_documents = [
|
||||
(master_doc, 'AdafruitDisplay_TextLibrary', u'Adafruit Display_Text Library Documentation',
|
||||
author, 'AdafruitDisplay_TextLibrary', 'One line description of project.',
|
||||
'Miscellaneous'),
|
||||
(
|
||||
master_doc,
|
||||
"AdafruitDisplay_TextLibrary",
|
||||
"Adafruit Display_Text Library Documentation",
|
||||
author,
|
||||
"AdafruitDisplay_TextLibrary",
|
||||
"One line description of project.",
|
||||
"Miscellaneous",
|
||||
),
|
||||
]
|
||||
|
|
|
|||
63
examples/display_text_anchored_position.py
Normal file
63
examples/display_text_anchored_position.py
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
"""
|
||||
This examples shows the use of anchor_point and anchored_position.
|
||||
"""
|
||||
import board
|
||||
import terminalio
|
||||
import displayio
|
||||
from adafruit_display_text import label
|
||||
|
||||
DISPLAY_WIDTH = 320
|
||||
DISPLAY_HEIGHT = 240
|
||||
TEXT = "Hello"
|
||||
|
||||
text_area_top_left = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_top_left.anchor_point = (0.0, 0.0)
|
||||
text_area_top_left.anchored_position = (0, 0)
|
||||
|
||||
text_area_top_middle = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_top_middle.anchor_point = (0.5, 0.0)
|
||||
text_area_top_middle.anchored_position = (DISPLAY_WIDTH / 2, 0)
|
||||
|
||||
text_area_top_right = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_top_right.anchor_point = (1.0, 0.0)
|
||||
text_area_top_right.anchored_position = (DISPLAY_WIDTH, 0)
|
||||
|
||||
text_area_middle_left = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_middle_left.anchor_point = (0.0, 0.5)
|
||||
text_area_middle_left.anchored_position = (0, DISPLAY_HEIGHT / 2)
|
||||
|
||||
text_area_middle_middle = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_middle_middle.anchor_point = (0.5, 0.5)
|
||||
text_area_middle_middle.anchored_position = (DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 2)
|
||||
|
||||
text_area_middle_right = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_middle_right.anchor_point = (1.0, 0.5)
|
||||
text_area_middle_right.anchored_position = (DISPLAY_WIDTH, DISPLAY_HEIGHT / 2)
|
||||
|
||||
text_area_bottom_left = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_bottom_left.anchor_point = (0.0, 1.0)
|
||||
text_area_bottom_left.anchored_position = (0, DISPLAY_HEIGHT)
|
||||
|
||||
text_area_bottom_middle = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_bottom_middle.anchor_point = (0.5, 1.0)
|
||||
text_area_bottom_middle.anchored_position = (DISPLAY_WIDTH / 2, DISPLAY_HEIGHT)
|
||||
|
||||
text_area_bottom_right = label.Label(terminalio.FONT, text=TEXT)
|
||||
text_area_bottom_right.anchor_point = (1.0, 1.0)
|
||||
text_area_bottom_right.anchored_position = (DISPLAY_WIDTH, DISPLAY_HEIGHT)
|
||||
|
||||
text_group = displayio.Group(max_size=9)
|
||||
text_group.append(text_area_top_middle)
|
||||
text_group.append(text_area_top_left)
|
||||
text_group.append(text_area_top_right)
|
||||
text_group.append(text_area_middle_middle)
|
||||
text_group.append(text_area_middle_left)
|
||||
text_group.append(text_area_middle_right)
|
||||
text_group.append(text_area_bottom_middle)
|
||||
text_group.append(text_area_bottom_left)
|
||||
text_group.append(text_area_bottom_right)
|
||||
|
||||
board.DISPLAY.show(text_group)
|
||||
|
||||
while True:
|
||||
pass
|
||||
27
examples/display_text_background_color.py
Normal file
27
examples/display_text_background_color.py
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
"""
|
||||
This examples shows the use color and background_color
|
||||
"""
|
||||
import time
|
||||
import board
|
||||
import terminalio
|
||||
from adafruit_display_text import label
|
||||
|
||||
text = " Color Background Hello world"
|
||||
text_area = label.Label(
|
||||
terminalio.FONT, text=text, color=0x0000FF, background_color=0xFFAA00
|
||||
)
|
||||
text_area.x = 10
|
||||
text_area.y = 10
|
||||
|
||||
print("background color is {:06x}".format(text_area.background_color))
|
||||
|
||||
board.DISPLAY.show(text_area)
|
||||
|
||||
time.sleep(2)
|
||||
text_area.background_color = 0xFF0000
|
||||
print("background color is {:06x}".format(text_area.background_color))
|
||||
time.sleep(2)
|
||||
text_area.background_color = None
|
||||
print("background color is {}".format(text_area.background_color))
|
||||
while True:
|
||||
pass
|
||||
125
examples/display_text_background_color_padding.py
Executable file
125
examples/display_text_background_color_padding.py
Executable file
|
|
@ -0,0 +1,125 @@
|
|||
"""
|
||||
This examples shows the use color and background_color
|
||||
"""
|
||||
import time
|
||||
import board
|
||||
import displayio
|
||||
|
||||
|
||||
# from adafruit_st7789 import ST7789
|
||||
from adafruit_ili9341 import ILI9341
|
||||
from adafruit_bitmap_font import bitmap_font
|
||||
from adafruit_display_text import label
|
||||
|
||||
# Setup the SPI display
|
||||
|
||||
print("Starting the display...") # goes to serial only
|
||||
displayio.release_displays()
|
||||
|
||||
|
||||
spi = board.SPI()
|
||||
tft_cs = board.D9 # arbitrary, pin not used
|
||||
tft_dc = board.D10
|
||||
tft_backlight = board.D12
|
||||
tft_reset = board.D11
|
||||
|
||||
while not spi.try_lock():
|
||||
spi.configure(baudrate=32000000)
|
||||
spi.unlock()
|
||||
|
||||
display_bus = displayio.FourWire(
|
||||
spi,
|
||||
command=tft_dc,
|
||||
chip_select=tft_cs,
|
||||
reset=tft_reset,
|
||||
baudrate=32000000,
|
||||
polarity=1,
|
||||
phase=1,
|
||||
)
|
||||
|
||||
print("spi.frequency: {}".format(spi.frequency))
|
||||
|
||||
DISPLAY_WIDTH = 320
|
||||
DISPLAY_HEIGHT = 240
|
||||
|
||||
# display = ST7789(display_bus, width=240, height=240, rotation=0, rowstart=80, colstart=0)
|
||||
display = ILI9341(
|
||||
display_bus,
|
||||
width=DISPLAY_WIDTH,
|
||||
height=DISPLAY_HEIGHT,
|
||||
rotation=180,
|
||||
auto_refresh=True,
|
||||
)
|
||||
|
||||
display.show(None)
|
||||
|
||||
# font=terminalio.FONT # this is the Builtin fixed dimension font
|
||||
|
||||
font = bitmap_font.load_font("fonts/Helvetica-Bold-16.bdf")
|
||||
|
||||
|
||||
text = []
|
||||
text.append("none") # no ascenders or descenders
|
||||
text.append("pop quops") # only descenders
|
||||
text.append("MONSTERs are tall") # only ascenders
|
||||
text.append("MONSTERs ate pop quops") # both ascenders and descenders
|
||||
text.append("MONSTER quops\nnewline quops") # with newline
|
||||
|
||||
display.auto_refresh = True
|
||||
myGroup = displayio.Group(max_size=6)
|
||||
display.show(myGroup)
|
||||
|
||||
text_area = []
|
||||
myPadding = 4
|
||||
|
||||
for i, thisText in enumerate(text):
|
||||
text_area.append(
|
||||
label.Label(
|
||||
font,
|
||||
text=thisText,
|
||||
color=0xFFFFFF,
|
||||
background_color=None,
|
||||
background_tight=False,
|
||||
padding_top=myPadding,
|
||||
padding_bottom=myPadding,
|
||||
padding_left=myPadding,
|
||||
padding_right=myPadding,
|
||||
)
|
||||
)
|
||||
|
||||
this_x = 10
|
||||
this_y = 10 + i * 40
|
||||
text_area[i].x = 10
|
||||
text_area[i].y = 3 + i * 50
|
||||
text_area[i].anchor_point = (0, 0)
|
||||
text_area[i].anchored_position = (this_x, this_y)
|
||||
myGroup.append(text_area[i])
|
||||
|
||||
print("background color is {}".format(text_area[0].background_color))
|
||||
|
||||
|
||||
while True:
|
||||
time.sleep(2)
|
||||
text_area[0].text = "text" # change some text in an existing text box
|
||||
# Note: changed text must fit within existing number of characters
|
||||
# when the Label was created
|
||||
|
||||
for area in text_area:
|
||||
area.background_color = 0xFF0000
|
||||
print("background color is {:06x}".format(text_area[0].background_color))
|
||||
time.sleep(2)
|
||||
for area in text_area:
|
||||
area.background_color = 0x000088
|
||||
print("background color is {:06x}".format(text_area[0].background_color))
|
||||
time.sleep(2)
|
||||
for area in text_area:
|
||||
area.background_color = 0x00FF00
|
||||
print("background color is {:06x}".format(text_area[0].background_color))
|
||||
time.sleep(2)
|
||||
for area in text_area:
|
||||
area.background_color = 0xFF0000
|
||||
print("background color is {:06x}".format(text_area[0].background_color))
|
||||
time.sleep(2)
|
||||
for area in text_area:
|
||||
area.background_color = None
|
||||
print("background color is {}".format(text_area[0].background_color))
|
||||
12
examples/display_text_bitmap_label_simpletest.py
Normal file
12
examples/display_text_bitmap_label_simpletest.py
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import board
|
||||
import terminalio
|
||||
from adafruit_display_text import bitmap_label
|
||||
|
||||
|
||||
text = "Hello world"
|
||||
text_area = bitmap_label.Label(terminalio.FONT, text=text)
|
||||
text_area.x = 10
|
||||
text_area.y = 10
|
||||
board.DISPLAY.show(text_area)
|
||||
while True:
|
||||
pass
|
||||
222
examples/display_text_label_vs_bitmap_label_comparison.py
Normal file
222
examples/display_text_label_vs_bitmap_label_comparison.py
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
# Sample for comparing label and bitmap_label positioning with Builtin or loaded BDF fonts
|
||||
|
||||
# pylint: disable=no-member
|
||||
|
||||
import gc
|
||||
import board
|
||||
import displayio
|
||||
import terminalio
|
||||
from adafruit_bitmap_font import bitmap_font
|
||||
|
||||
from adafruit_display_text import bitmap_label
|
||||
from adafruit_display_text import label
|
||||
|
||||
# pylint: disable=no-member
|
||||
|
||||
|
||||
##########
|
||||
# Use this Boolean variables to select which font style to use
|
||||
##########
|
||||
use_builtinfont = False # Set True to use the terminalio.FONT BuiltinFont,
|
||||
fontToUse = terminalio.FONT
|
||||
# Set False to use a BDF loaded font, see "fontFiles" below
|
||||
##########
|
||||
|
||||
if not use_builtinfont:
|
||||
# load the fonts
|
||||
print("loading font...")
|
||||
|
||||
fontList = []
|
||||
|
||||
# Load some proportional fonts
|
||||
fontFile = "fonts/Helvetica-Bold-16.bdf"
|
||||
fontToUse = bitmap_font.load_font(fontFile)
|
||||
|
||||
# Set scaling factor for display text
|
||||
my_scale = 1
|
||||
|
||||
# Setup the SPI display
|
||||
if "DISPLAY" not in dir(board):
|
||||
# Setup the LCD display with driver
|
||||
# You may need to change this to match the display driver for the chipset
|
||||
# used on your display
|
||||
from adafruit_ili9341 import ILI9341
|
||||
|
||||
displayio.release_displays()
|
||||
|
||||
# setup the SPI bus
|
||||
spi = board.SPI()
|
||||
tft_cs = board.D9 # arbitrary, pin not used
|
||||
tft_dc = board.D10
|
||||
tft_backlight = board.D12
|
||||
tft_reset = board.D11
|
||||
|
||||
while not spi.try_lock():
|
||||
spi.configure(baudrate=32000000)
|
||||
spi.unlock()
|
||||
|
||||
display_bus = displayio.FourWire(
|
||||
spi,
|
||||
command=tft_dc,
|
||||
chip_select=tft_cs,
|
||||
reset=tft_reset,
|
||||
baudrate=32000000,
|
||||
polarity=1,
|
||||
phase=1,
|
||||
)
|
||||
|
||||
# Number of pixels in the display
|
||||
DISPLAY_WIDTH = 320
|
||||
DISPLAY_HEIGHT = 240
|
||||
|
||||
# create the display
|
||||
display = ILI9341(
|
||||
display_bus,
|
||||
width=DISPLAY_WIDTH,
|
||||
height=DISPLAY_HEIGHT,
|
||||
rotation=180, # The rotation can be adjusted to match your configuration.
|
||||
auto_refresh=True,
|
||||
native_frames_per_second=90,
|
||||
)
|
||||
|
||||
# reset the display to show nothing.
|
||||
display.show(None)
|
||||
else:
|
||||
# built-in display
|
||||
display = board.DISPLAY
|
||||
|
||||
print("Display is started")
|
||||
|
||||
|
||||
preload_glyphs = (
|
||||
True # set this to True if you want to preload the font glyphs into memory
|
||||
)
|
||||
# preloading the glyphs will help speed up the rendering of text but will use more RAM
|
||||
|
||||
if preload_glyphs and not use_builtinfont:
|
||||
|
||||
# identify the glyphs to load into memory -> increases rendering speed
|
||||
glyphs = (
|
||||
b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/-_,.:?!'\n "
|
||||
)
|
||||
|
||||
print("loading glyphs...")
|
||||
fontToUse.load_glyphs(glyphs)
|
||||
|
||||
print("Glyphs are loaded.")
|
||||
|
||||
print("Fonts completed loading.")
|
||||
|
||||
# create group
|
||||
|
||||
long_string = "The purple snake\nbrings python fun\nto everyone."
|
||||
label2_padding = 10
|
||||
|
||||
#####
|
||||
# Create the "bitmap_label.py" versions of the text labels.
|
||||
|
||||
gc.collect()
|
||||
bitmap_label_start = gc.mem_free()
|
||||
|
||||
bmap_label1 = bitmap_label.Label(
|
||||
font=fontToUse,
|
||||
text="bitmap_label",
|
||||
color=0xFFFFFF,
|
||||
background_color=0xFF0000,
|
||||
padding_bottom=0,
|
||||
padding_left=0,
|
||||
padding_right=0,
|
||||
padding_top=0,
|
||||
background_tight=True,
|
||||
line_spacing=1.25,
|
||||
scale=my_scale,
|
||||
anchor_point=(0.0, 0),
|
||||
anchored_position=(10, 60),
|
||||
)
|
||||
|
||||
bmap_label2 = bitmap_label.Label(
|
||||
font=fontToUse,
|
||||
text=long_string,
|
||||
color=0x000000,
|
||||
max_glyphs=len(long_string),
|
||||
background_color=0xFFFF00,
|
||||
padding_bottom=label2_padding,
|
||||
padding_left=0,
|
||||
padding_right=0,
|
||||
padding_top=label2_padding,
|
||||
background_tight=False,
|
||||
line_spacing=1.25,
|
||||
scale=my_scale,
|
||||
anchor_point=(0.0, 0),
|
||||
anchored_position=(10, 120),
|
||||
)
|
||||
|
||||
gc.collect()
|
||||
bitmap_label_end = gc.mem_free()
|
||||
|
||||
print("bitmap_label used: {} memory".format(bitmap_label_start - bitmap_label_end))
|
||||
|
||||
bmap_group = displayio.Group(max_size=4) # Create a group for displaying
|
||||
bmap_group.append(bmap_label1)
|
||||
bmap_group.append(bmap_label2)
|
||||
|
||||
|
||||
#####
|
||||
# Create the "label.py" versions of the text labels.
|
||||
|
||||
gc.collect()
|
||||
label_start = gc.mem_free()
|
||||
|
||||
label1 = label.Label(
|
||||
font=fontToUse,
|
||||
text="label",
|
||||
color=0xFFFFFF,
|
||||
background_color=0xFF0000,
|
||||
padding_bottom=0,
|
||||
padding_left=0,
|
||||
padding_right=0,
|
||||
padding_top=0,
|
||||
background_tight=True,
|
||||
line_spacing=1.25,
|
||||
scale=my_scale,
|
||||
anchor_point=(1.0, 0),
|
||||
anchored_position=(display.width - 10, 60),
|
||||
)
|
||||
|
||||
label2 = label.Label(
|
||||
font=fontToUse,
|
||||
text=long_string,
|
||||
color=0x000000,
|
||||
max_glyphs=len(long_string),
|
||||
background_color=0xFFFF00,
|
||||
padding_bottom=label2_padding,
|
||||
padding_left=0,
|
||||
padding_right=0,
|
||||
padding_top=label2_padding,
|
||||
background_tight=False,
|
||||
line_spacing=1.25,
|
||||
scale=my_scale,
|
||||
anchor_point=(1.0, 0),
|
||||
anchored_position=(display.width - 10, 120),
|
||||
)
|
||||
|
||||
gc.collect()
|
||||
label_end = gc.mem_free()
|
||||
|
||||
print("label used: {} memory".format(label_start - label_end))
|
||||
label_group = displayio.Group(max_size=4) # Create a group for displaying
|
||||
label_group.append(label1)
|
||||
label_group.append(label2)
|
||||
|
||||
|
||||
print("***")
|
||||
|
||||
main_group = displayio.Group()
|
||||
main_group.append(label_group)
|
||||
main_group.append(bmap_group)
|
||||
|
||||
display.auto_refresh = True
|
||||
|
||||
display.show(main_group)
|
||||
while True:
|
||||
pass
|
||||
|
|
@ -1,25 +1,25 @@
|
|||
"""
|
||||
This example show the use of the backlight as well as using labels to simulate
|
||||
a terminal using a font on the PyPortal
|
||||
"""
|
||||
|
||||
import os
|
||||
import time
|
||||
import board
|
||||
import pulseio
|
||||
import microcontroller
|
||||
import displayio
|
||||
|
||||
from adafruit_bitmap_font import bitmap_font
|
||||
from adafruit_display_text.label import Label
|
||||
|
||||
backlight = pulseio.PWMOut(microcontroller.pin.PB21) #pylint: disable=no-member
|
||||
|
||||
max_brightness = 2 ** 15
|
||||
|
||||
fonts = list(filter(lambda x: x.endswith("bdf") and not x.startswith("."), os.listdir("/")))
|
||||
fonts = list(
|
||||
filter(lambda x: x.endswith("bdf") and not x.startswith("."), os.listdir("/"))
|
||||
)
|
||||
fonts = [bitmap_font.load_font(x) for x in fonts]
|
||||
|
||||
|
||||
print("fade up")
|
||||
# Fade up the backlight
|
||||
for b in range(100):
|
||||
backlight.duty_cycle = b * max_brightness // 100
|
||||
board.DISPLAY.brightness = b / 100
|
||||
time.sleep(0.01) # default (0.01)
|
||||
|
||||
demos = ["CircuitPython = Code + Community", "accents - üàêùéáçãÍóí", "others - αψ◌"]
|
||||
|
|
@ -38,16 +38,19 @@ for demo_text in demos:
|
|||
y += area.height
|
||||
|
||||
# Wait for the image to load.
|
||||
try:
|
||||
board.DISPLAY.refresh(target_frames_per_second=60)
|
||||
except AttributeError:
|
||||
board.DISPLAY.wait_for_frame()
|
||||
|
||||
# Wait forever
|
||||
# Wait for 10 minutes (600 seconds)
|
||||
time.sleep(600)
|
||||
|
||||
# Fade down the backlight
|
||||
for b in range(50, -1, -1):
|
||||
backlight.duty_cycle = b * max_brightness // 100
|
||||
time.sleep(0.005) # default (0.005)
|
||||
for b in range(100, -1, -1):
|
||||
board.DISPLAY.brightness = b / 100
|
||||
time.sleep(0.01) # default (0.01)
|
||||
|
||||
print("fade down")
|
||||
|
||||
# splash.pop()
|
||||
time.sleep(10)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
import board
|
||||
import terminalio
|
||||
from adafruit_display_text import label
|
||||
|
||||
|
||||
text = "Hello world"
|
||||
text_area = label.Label(terminalio.FONT, text=text)
|
||||
text_area.x = 10
|
||||
text_area.y = 10
|
||||
board.DISPLAY.show(text_area)
|
||||
while True:
|
||||
pass
|
||||
|
|
@ -1,15 +1,19 @@
|
|||
import os
|
||||
import board
|
||||
import displayio
|
||||
from adafruit_display_text.label import Label
|
||||
from adafruit_bitmap_font import bitmap_font
|
||||
from adafruit_display_text.label import Label
|
||||
|
||||
|
||||
# the current working directory (where this file is)
|
||||
cwd = ("/"+__file__).rsplit('/', 1)[0]
|
||||
fonts = [file for file in os.listdir(cwd+"/fonts/")
|
||||
if (file.endswith(".bdf") and not file.startswith("._"))]
|
||||
cwd = ("/" + __file__).rsplit("/", 1)[0]
|
||||
fonts = [
|
||||
file
|
||||
for file in os.listdir(cwd + "/fonts/")
|
||||
if (file.endswith(".bdf") and not file.startswith("._"))
|
||||
]
|
||||
for i, filename in enumerate(fonts):
|
||||
fonts[i] = cwd+"/fonts/"+filename
|
||||
fonts[i] = cwd + "/fonts/" + filename
|
||||
print(fonts)
|
||||
|
||||
##########################################################################
|
||||
|
|
@ -26,14 +30,12 @@ board.DISPLAY.show(splash)
|
|||
color_bitmap = displayio.Bitmap(320, 240, 1)
|
||||
color_palette = displayio.Palette(1)
|
||||
color_palette[0] = 0xFFFFFF
|
||||
bg_sprite = displayio.TileGrid(color_bitmap,
|
||||
pixel_shader=color_palette,
|
||||
x=0, y=0)
|
||||
bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
|
||||
splash.append(bg_sprite)
|
||||
|
||||
# Load the font
|
||||
font = bitmap_font.load_font(THE_FONT)
|
||||
font.load_glyphs(DISPLAY_STRING.encode('utf-8'))
|
||||
font.load_glyphs(DISPLAY_STRING.encode("utf-8"))
|
||||
|
||||
print(DISPLAY_STRING)
|
||||
|
||||
|
|
@ -48,13 +50,16 @@ print(dims)
|
|||
textbg_bitmap = displayio.Bitmap(dims[2], dims[3], 1)
|
||||
textbg_palette = displayio.Palette(1)
|
||||
textbg_palette[0] = 0xFF0000
|
||||
textbg_sprite = displayio.TileGrid(textbg_bitmap,
|
||||
pixel_shader=textbg_palette,
|
||||
x=text.x+dims[0], y=text.y+dims[1])
|
||||
textbg_sprite = displayio.TileGrid(
|
||||
textbg_bitmap, pixel_shader=textbg_palette, x=text.x + dims[0], y=text.y + dims[1]
|
||||
)
|
||||
splash.append(textbg_sprite)
|
||||
splash.append(text)
|
||||
board.DISPLAY.refresh_soon()
|
||||
board.DISPLAY.wait_for_frame()
|
||||
try:
|
||||
board.DISPLAY.refresh(target_frames_per_second=60)
|
||||
except AttributeError:
|
||||
board.DISPLAY.refresh_soon()
|
||||
board.DISPLAY.wait_for_frame()
|
||||
|
||||
|
||||
while True:
|
||||
|
|
|
|||
4194
fonts/Helvetica-Bold-16.bdf
Executable file
4194
fonts/Helvetica-Bold-16.bdf
Executable file
File diff suppressed because it is too large
Load diff
|
|
@ -1,2 +1,2 @@
|
|||
Adafruit-Blinka
|
||||
|
||||
adafruit-blinka-displayio
|
||||
|
|
|
|||
50
setup.py
Normal file
50
setup.py
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
"""A setuptools based setup module.
|
||||
See:
|
||||
https://packaging.python.org/en/latest/distributing.html
|
||||
https://github.com/pypa/sampleproject
|
||||
"""
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
|
||||
# To use a consistent encoding
|
||||
from codecs import open
|
||||
from os import path
|
||||
|
||||
here = path.abspath(path.dirname(__file__))
|
||||
|
||||
# Get the long description from the README file
|
||||
with open(path.join(here, "README.rst"), encoding="utf-8") as f:
|
||||
long_description = f.read()
|
||||
|
||||
setup(
|
||||
name="adafruit-circuitpython-display-text",
|
||||
use_scm_version=True,
|
||||
setup_requires=["setuptools_scm"],
|
||||
description="Displays text using CircuitPython's displayio.",
|
||||
long_description=long_description,
|
||||
long_description_content_type="text/x-rst",
|
||||
# The project's main homepage.
|
||||
url="https://github.com/adafruit/Adafruit_CircuitPython_Display_Text",
|
||||
# Author details
|
||||
author="Adafruit Industries",
|
||||
author_email="circuitpython@adafruit.com",
|
||||
install_requires=["Adafruit-Blinka", "adafruit-blinka-displayio",],
|
||||
# Choose your license
|
||||
license="MIT",
|
||||
# See https://pypi.python.org/pypi?%3Aaction=list_classifiers
|
||||
classifiers=[
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
"Topic :: System :: Hardware",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
"Programming Language :: Python :: 3.5",
|
||||
],
|
||||
# What does your project relate to?
|
||||
keywords="adafruit blinka circuitpython micropython bitmap fonts text display tft lcd displayio",
|
||||
# You can just specify the packages manually here if your project is
|
||||
# simple. Or you can use find_packages().
|
||||
packages=["adafruit_display_text"],
|
||||
)
|
||||
Loading…
Reference in a new issue