mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
ci: add MicroPython test (#4997)
Co-authored-by: Gabor Kiss-Vamosi <kisvegabor@gmail.com>
This commit is contained in:
parent
1d0dd9b28b
commit
32c6bc5bd7
13
.github/workflows/build_micropython.yml
vendored
13
.github/workflows/build_micropython.yml
vendored
@ -66,10 +66,19 @@ jobs:
|
||||
# Unix port
|
||||
- name: Build Unix port
|
||||
if: matrix.port == 'unix'
|
||||
run: make -j $(nproc) -C ports/unix DEBUG=1
|
||||
run: make -j $(nproc) -C ports/unix DEBUG=1 LV_CFLAGS="-DMICROPY_LV_USE_LOG=0"
|
||||
- name: Install requirements for the test
|
||||
run: |
|
||||
python3 -m pip install pillow
|
||||
mkdir lib/lv_bindings/lvgl/tests/micropy_test/artifacts
|
||||
- name: Run tests
|
||||
if: success() && matrix.port == 'unix'
|
||||
run: |
|
||||
export XDG_RUNTIME_DIR=/tmp
|
||||
lib/lv_bindings/tests/run.sh
|
||||
python3 lib/lv_bindings/lvgl/tests/micropy_test/__init__.py --artifact-path=lib/lv_bindings/lvgl/tests/micropy_test/artifacts --mpy-path=ports/unix/build-standard/micropython
|
||||
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: test-artifacts
|
||||
path: lib/lv_bindings/lvgl/tests/micropy_test/artifacts
|
||||
|
@ -956,10 +956,9 @@ static lv_result_t decompress_image(lv_image_decoder_dsc_t * dsc, const lv_image
|
||||
}
|
||||
|
||||
uint8_t * img_data;
|
||||
uint32_t out_len = compressed->decompressed_size;
|
||||
uint32_t input_len = compressed->compressed_size;
|
||||
LV_UNUSED(input_len);
|
||||
uint32_t out_len = compressed->decompressed_size;
|
||||
|
||||
lv_draw_buf_t * decompressed = lv_draw_buf_create(dsc->header.w, dsc->header.h, dsc->header.cf,
|
||||
dsc->header.stride);
|
||||
if(decompressed == NULL) {
|
||||
|
370
tests/micropy_test/__init__.py
Normal file
370
tests/micropy_test/__init__.py
Normal file
@ -0,0 +1,370 @@
|
||||
"""
|
||||
The test script will only run the one test on microptyhon. It is not a
|
||||
framework that can be used for other tests. This has a reduced code footprint.
|
||||
entrypoint API is almost the same as the framework.
|
||||
|
||||
|
||||
Requirements
|
||||
Python >= 3.10
|
||||
|
||||
pillow library
|
||||
|
||||
add the following to the CI prior to the test running
|
||||
|
||||
python3 -m pip install pillow
|
||||
|
||||
Example command line to run the test. I suggest doing this from the root of the
|
||||
binding directory. It is just a simple location to do it from.
|
||||
|
||||
Paths that are passed in MUST be relitive to the current working directory.
|
||||
python3 lib/lv_bindings/lvgl/tests/micropy_test/__init__.py --artifact-path=lib/lv_bindings/lvgl/tests/micropy_test/artifacts --mpy-path=ports/unix/build-standard/micropython
|
||||
|
||||
"""
|
||||
import os
|
||||
import time
|
||||
import signal
|
||||
import argparse
|
||||
import binascii
|
||||
import unittest
|
||||
import threading
|
||||
import subprocess
|
||||
|
||||
from PIL import Image as Image
|
||||
|
||||
|
||||
DEBUG = 0
|
||||
|
||||
debug_log = None
|
||||
|
||||
|
||||
def log(*args):
|
||||
args = ' '.join(repr(arg) for arg in args)
|
||||
debug_log.write(args + '\n')
|
||||
|
||||
if DEBUG:
|
||||
sys.stdout.write('\033[31;1m' + args + '\033[0m\n')
|
||||
sys.stdout.flush()
|
||||
|
||||
|
||||
BASE_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__)))
|
||||
TEST_PATH = os.path.join(BASE_PATH, 'micropy.py')
|
||||
IMG_PATH = os.path.join(BASE_PATH, '../ref_imgs/binding.png')
|
||||
|
||||
CTRL_C = b'\x03' # 2 times to exit any running code
|
||||
CTRL_D = b'\x04' # exit paste mode committing and running what has been pasted
|
||||
CTRL_E = b'\x05' # enter paste mode
|
||||
|
||||
PASTE_PROMPT = b'==='
|
||||
REPL_PROMPT = b'>>>'
|
||||
|
||||
os.environ['MICROPYINSPECT'] = '1'
|
||||
|
||||
|
||||
class TestData:
|
||||
|
||||
def __init__(self):
|
||||
self.watchdog_timer = time.time()
|
||||
self.result = None
|
||||
self.error_data = ''
|
||||
self.event = threading.Event()
|
||||
|
||||
|
||||
class MicroPython_Test(unittest.TestCase):
|
||||
# these are here simply to make an IDE happy. Their values get dynamically
|
||||
# set when the class gets constructed
|
||||
process: subprocess.Popen = None
|
||||
exit_event: threading.Event = None
|
||||
|
||||
@classmethod
|
||||
def send(cls, cmd):
|
||||
if cls.process is None:
|
||||
return
|
||||
|
||||
log('<---', cmd)
|
||||
cls.process.stdin.write(cmd)
|
||||
cls.process.stdin.flush()
|
||||
|
||||
@classmethod
|
||||
def read_until(cls, marker):
|
||||
micropy_data = b''
|
||||
error_data = b''
|
||||
|
||||
log('MARKER', marker)
|
||||
|
||||
logged = False
|
||||
|
||||
while (
|
||||
not micropy_data.endswith(marker) and
|
||||
not cls.exit_event.is_set()
|
||||
):
|
||||
try:
|
||||
char = cls.process.stdout.read(1)
|
||||
except: # NOQA
|
||||
break
|
||||
|
||||
if char:
|
||||
micropy_data += char
|
||||
logged = False
|
||||
else:
|
||||
logged = True
|
||||
log('--->', micropy_data)
|
||||
|
||||
if micropy_data.endswith(b'\nERROR END\n'):
|
||||
error_data = micropy_data.split(b'\nERROR START\n')[-1].split(b'\nERROR END\n')[0]
|
||||
micropy_data = b''
|
||||
log('---> ERROR: ', error_data)
|
||||
logged = True
|
||||
break
|
||||
|
||||
if not logged:
|
||||
log('--->', micropy_data)
|
||||
|
||||
if cls.exit_event.is_set():
|
||||
log('--EXIT EVENT SET')
|
||||
|
||||
if micropy_data:
|
||||
return micropy_data.replace(marker, b''), error_data
|
||||
|
||||
return micropy_data, error_data
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
os.chdir(os.path.dirname(__file__))
|
||||
cls.exit_event = threading.Event()
|
||||
|
||||
log(f'--SETTING UP')
|
||||
cls.process = subprocess.Popen(
|
||||
['bash'],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE,
|
||||
stdin=subprocess.PIPE,
|
||||
env=os.environ,
|
||||
shell=True,
|
||||
preexec_fn=os.setsid
|
||||
)
|
||||
log(f'--RUNNING MICROPYTHON ({MICROPYTHON_PATH})')
|
||||
|
||||
cls.send(b'cd ' + os.path.dirname(__file__).encode('utf-8') + b'\n')
|
||||
cls.send(MICROPYTHON_PATH.encode('utf-8') + b'\n')
|
||||
_, error_data = cls.read_until(b'>>>')
|
||||
|
||||
if error_data:
|
||||
raise RuntimeError(error_data)
|
||||
|
||||
log('--MICROPYTHON STARTED')
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
log('--TEARDOWN STARTED')
|
||||
|
||||
if cls.process is not None:
|
||||
cls.send(CTRL_C)
|
||||
cls.send(CTRL_C)
|
||||
cls.send(CTRL_D)
|
||||
|
||||
if not cls.process.stdin.closed:
|
||||
cls.process.stdin.close()
|
||||
|
||||
os.killpg(os.getpgid(cls.process.pid), signal.SIGTERM)
|
||||
|
||||
cls.process.wait()
|
||||
|
||||
if not cls.process.stdout.closed:
|
||||
cls.process.stdout.close()
|
||||
|
||||
if not cls.process.stderr.closed:
|
||||
cls.process.stderr.close()
|
||||
|
||||
cls.process = None
|
||||
|
||||
log(f'--TEARDOWN FINISHED')
|
||||
|
||||
def test_1_image_compare(self):
|
||||
image = Image.open(IMG_PATH)
|
||||
res_img = image.convert('RGB')
|
||||
image.close()
|
||||
res_data = list(res_img.getdata())
|
||||
res_img.close()
|
||||
|
||||
with open(TEST_PATH, 'rb') as f:
|
||||
test_code = f.read()
|
||||
|
||||
log(f'--RUNNING TEST ({TEST_PATH})')
|
||||
|
||||
test_code = test_code.strip()
|
||||
|
||||
if self.__class__.process is None:
|
||||
self.fail('MicroPython failure.')
|
||||
|
||||
self.send(CTRL_E)
|
||||
|
||||
_, error_data = self.read_until(PASTE_PROMPT)
|
||||
if error_data:
|
||||
self.fail(error_data)
|
||||
|
||||
test_code = test_code.split(b'\r\n')
|
||||
|
||||
for i, line in enumerate(test_code):
|
||||
self.send(line + b'\n')
|
||||
_, error_data = self.read_until(b'\n')
|
||||
|
||||
if error_data:
|
||||
self.fail(error_data)
|
||||
|
||||
time.sleep(0.002)
|
||||
|
||||
# self.read_until(b'# end\n')
|
||||
|
||||
def _do(td: TestData):
|
||||
self.send(CTRL_D)
|
||||
td.error_data = b''
|
||||
td.watchdog_timer = time.time()
|
||||
|
||||
td.result = []
|
||||
|
||||
try:
|
||||
_, td.error_data = self.read_until(b'FRAME START\n')
|
||||
td.watchdog_timer = time.time()
|
||||
|
||||
lne, td.error_data = self.read_until(b'\n')
|
||||
|
||||
while (
|
||||
b'FRAME END' not in lne and
|
||||
not td.error_data and
|
||||
not self.__class__.exit_event.is_set()
|
||||
):
|
||||
td.watchdog_timer = time.time()
|
||||
td.result.append(lne)
|
||||
lne, td.error_data = self.read_until(b'\n')
|
||||
|
||||
if td.error_data:
|
||||
return
|
||||
|
||||
if self.__class__.exit_event.is_set():
|
||||
return
|
||||
|
||||
except: # NOQA
|
||||
import traceback
|
||||
|
||||
traceback.print_exc()
|
||||
|
||||
td.error_data = traceback.format_exc()
|
||||
return
|
||||
|
||||
td.event.set()
|
||||
|
||||
test_data = TestData()
|
||||
|
||||
t = threading.Thread(
|
||||
target=_do,
|
||||
args=(test_data,)
|
||||
)
|
||||
t.daemon = True
|
||||
test_data.watchdog_timer = time.time()
|
||||
|
||||
t.start()
|
||||
|
||||
while (
|
||||
(time.time() - test_data.watchdog_timer) * 1000 <= 20000 and
|
||||
not test_data.event.is_set()
|
||||
):
|
||||
test_data.event.wait(0.05)
|
||||
|
||||
if not test_data.event.is_set():
|
||||
self.__class__.exit_event.set()
|
||||
# self.read_until(REPL_PROMPT)
|
||||
|
||||
self.send(CTRL_C)
|
||||
self.send(CTRL_C)
|
||||
|
||||
width = 800
|
||||
height = 480
|
||||
|
||||
if test_data.error_data:
|
||||
self.fail(test_data.error_data)
|
||||
|
||||
try:
|
||||
frame = bytearray(
|
||||
b''.join(binascii.unhexlify(lne) for lne in test_data.result)
|
||||
)
|
||||
|
||||
# I don't exactly know why the byte order is backwards but it is
|
||||
frame = bytes(bytearray([
|
||||
item for j in range(0, len(frame), 3)
|
||||
for item in [frame[j + 2], frame[j + 1], frame[j]]
|
||||
]))
|
||||
|
||||
image = Image.new('RGB', (width, height))
|
||||
image.frombytes(frame)
|
||||
img = image.convert('RGB')
|
||||
image.close()
|
||||
|
||||
byte_data = list(img.getdata())
|
||||
img.save(os.path.join(ARTIFACT_PATH, f'frame.png'), 'PNG')
|
||||
img.close()
|
||||
|
||||
with open(os.path.join(ARTIFACT_PATH, f'frame.bin'), 'wb') as f:
|
||||
# have to flatten the data and remove the alpha
|
||||
# from the PIL image it is formatted as
|
||||
# [(r, g, b), (r, g, b)]
|
||||
f.write(bytes(bytearray([
|
||||
item for sublist in byte_data
|
||||
for item in sublist
|
||||
])))
|
||||
|
||||
except: # NOQA
|
||||
import traceback
|
||||
|
||||
self.fail(traceback.format_exc())
|
||||
|
||||
self.assertEqual(res_data, byte_data, 'Frames do not match')
|
||||
|
||||
|
||||
cwd = os.path.abspath(os.getcwd())
|
||||
|
||||
ARTIFACT_PATH = os.path.join(cwd, 'artifacts')
|
||||
MICROPYTHON_PATH = os.path.join(cwd, 'micropython')
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
import sys
|
||||
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
arg_parser.add_argument(
|
||||
'--artifact-path',
|
||||
dest='artifact_path',
|
||||
help='path to save artifacts to',
|
||||
action='store'
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
'--mpy-path',
|
||||
dest='mpy_path',
|
||||
help='path to micropython',
|
||||
action='store'
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
'--debug',
|
||||
dest='debug',
|
||||
help='debug output',
|
||||
action='store_true'
|
||||
)
|
||||
|
||||
args = arg_parser.parse_args()
|
||||
|
||||
ARTIFACT_PATH = os.path.join(cwd, args.artifact_path)
|
||||
MICROPYTHON_PATH = os.path.join(cwd, args.mpy_path)
|
||||
DEBUG = args.debug
|
||||
|
||||
if not os.path.exists(ARTIFACT_PATH):
|
||||
raise RuntimeError(f'Artifact path does not exist ({ARTIFACT_PATH})')
|
||||
|
||||
if not os.path.exists(MICROPYTHON_PATH):
|
||||
raise RuntimeError(f'MicroPython binary not found ({MICROPYTHON_PATH})')
|
||||
|
||||
debug_log_path = os.path.join(ARTIFACT_PATH, 'debug.log')
|
||||
debug_log = open(debug_log_path, 'w')
|
||||
|
||||
unittest.main(argv=[sys.argv[0], '-v'])
|
||||
|
||||
debug_log.close()
|
||||
print(f'View the debug output in "{debug_log_path}"')
|
BIN
tests/micropy_test/font_montserrat_24.ttf
Normal file
BIN
tests/micropy_test/font_montserrat_24.ttf
Normal file
Binary file not shown.
BIN
tests/micropy_test/image_compare.png
Normal file
BIN
tests/micropy_test/image_compare.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
432
tests/micropy_test/micropy.py
Normal file
432
tests/micropy_test/micropy.py
Normal file
@ -0,0 +1,432 @@
|
||||
import io
|
||||
|
||||
import lvgl as lv
|
||||
import ubinascii
|
||||
import fs_driver
|
||||
import sys
|
||||
|
||||
|
||||
if not lv.is_initialized():
|
||||
lv.init()
|
||||
|
||||
try:
|
||||
lv.log_register_print_cb # NOQA
|
||||
|
||||
raise RuntimeError('Logging in LVGL MUST be disabled to run the tests.')
|
||||
except AttributeError:
|
||||
pass
|
||||
except RuntimeError as exc:
|
||||
buf = io.StringIO()
|
||||
sys.print_exception(exc, buf)
|
||||
|
||||
print('ERROR START')
|
||||
print(buf.getvalue())
|
||||
print('ERROR END')
|
||||
raise
|
||||
|
||||
fs_drv = lv.fs_drv_t()
|
||||
fs_driver.fs_register(fs_drv, 'A')
|
||||
|
||||
WIDTH = 800
|
||||
HEIGHT = 480
|
||||
|
||||
|
||||
def test_func_wrapper(func):
|
||||
def _wrapper(*args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except Exception as exc:
|
||||
buf = io.StringIO()
|
||||
sys.print_exception(exc, buf)
|
||||
|
||||
print('ERROR START')
|
||||
print(buf.getvalue())
|
||||
print('ERROR END')
|
||||
|
||||
return _wrapper
|
||||
|
||||
|
||||
CAPTURE_FRAME = False
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def flush(disp, area, color_p):
|
||||
|
||||
x1 = area.x1
|
||||
x2 = area.x2
|
||||
y1 = area.y1
|
||||
y2 = area.y2
|
||||
|
||||
size = (x2 - x1 + 1) * (y2 - y1 + 1) * lv.color_format_get_size(
|
||||
disp.get_color_format()
|
||||
)
|
||||
data_view = color_p.__dereference__(size)
|
||||
byte_count = 0
|
||||
|
||||
print('FRAME START')
|
||||
sys.stdout.flush()
|
||||
|
||||
while byte_count != size:
|
||||
chunk_size = min(size - byte_count, 512)
|
||||
chunk = data_view[byte_count:chunk_size + byte_count]
|
||||
byte_count += chunk_size
|
||||
print(ubinascii.hexlify(bytes(chunk)).decode('utf-8'))
|
||||
sys.stdout.flush()
|
||||
|
||||
print('FRAME END')
|
||||
sys.stdout.flush()
|
||||
|
||||
disp.flush_ready()
|
||||
|
||||
|
||||
disp_drv = lv.display_create(WIDTH, HEIGHT)
|
||||
disp_drv.set_flush_cb(flush)
|
||||
disp_drv.set_color_format(lv.COLOR_FORMAT.RGB888)
|
||||
|
||||
color_size = lv.color_format_get_size(disp_drv.get_color_format())
|
||||
|
||||
buf = bytearray(WIDTH * HEIGHT * color_size)
|
||||
disp_drv.set_draw_buffers(
|
||||
buf,
|
||||
None,
|
||||
WIDTH * HEIGHT * color_size,
|
||||
lv.DISPLAY_RENDER_MODE.FULL
|
||||
)
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def GRID_FR(x):
|
||||
return lv.COORD.MAX - 100 + x
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def CANVAS_BUF_SIZE(w, h, bpp, stride):
|
||||
return ((((w * bpp + 7) >> 3) + stride - 1) & ~(
|
||||
stride - 1)) * h + lv.DRAW_BUF_ALIGN
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def create_ui():
|
||||
# Create a colors
|
||||
c1 = lv.color_hex(0xff0000)
|
||||
c2 = lv.palette_darken(lv.PALETTE.BLUE, 2)
|
||||
c3 = c1.mix(c2, lv.OPA._60)
|
||||
|
||||
# Create a style
|
||||
style_big_font = lv.style_t()
|
||||
style_big_font.init()
|
||||
|
||||
# Try to load as built in font and if not load it using tiny TTF
|
||||
try:
|
||||
font_montserrat_24 = lv.font_montserrat_24
|
||||
except AttributeError:
|
||||
font_montserrat_24 = lv.font_t()
|
||||
lv.tiny_ttf_create_file(font_montserrat_24, 'A:font_montserrat_24.ttf', 32)
|
||||
|
||||
style_big_font.set_text_font(font_montserrat_24)
|
||||
|
||||
# Get the active screen
|
||||
scr = lv.screen_active()
|
||||
|
||||
# Declare static array of integers, and test grid setting options
|
||||
gird_cols = [300, GRID_FR(3), GRID_FR(2), lv.GRID_TEMPLATE_LAST]
|
||||
gird_rows = [100, GRID_FR(1), lv.GRID_CONTENT, lv.GRID_TEMPLATE_LAST]
|
||||
scr.set_grid_dsc_array(gird_cols, gird_rows)
|
||||
|
||||
chart_type_subject = lv.subject_t()
|
||||
chart_type_subject.init_int(0)
|
||||
|
||||
# Create a widget
|
||||
dropdown = lv.dropdown(scr)
|
||||
|
||||
# Pass a string as argument
|
||||
dropdown.set_options("Lines\nBars")
|
||||
|
||||
# Use grid align options
|
||||
dropdown.set_grid_cell(
|
||||
lv.GRID_ALIGN.CENTER,
|
||||
0,
|
||||
1,
|
||||
lv.GRID_ALIGN.CENTER,
|
||||
0,
|
||||
1
|
||||
)
|
||||
|
||||
# Bind to a subject
|
||||
dropdown.bind_value(chart_type_subject)
|
||||
|
||||
# Create a chart with an external array of points
|
||||
chart = lv.chart(lv.screen_active())
|
||||
chart.set_grid_cell(lv.GRID_ALIGN.STRETCH, 0, 1, lv.GRID_ALIGN.CENTER, 1, 1)
|
||||
|
||||
series = chart.add_series(c3, lv.chart.AXIS.PRIMARY_X)
|
||||
|
||||
chart_y_array = [10, 25, 50, 40, 30, 35, 60, 65, 70, 75]
|
||||
|
||||
chart.set_ext_y_array(series, chart_y_array)
|
||||
|
||||
# Add custom observer callback
|
||||
chart_type_subject.add_observer_obj(
|
||||
lambda _, __: chart_type_observer_cb(chart, chart_type_subject),
|
||||
chart,
|
||||
None
|
||||
)
|
||||
|
||||
# Manually set the subject's value
|
||||
chart_type_subject.set_int(1)
|
||||
|
||||
label = lv.label(scr)
|
||||
label.set_grid_cell(lv.GRID_ALIGN.START, 1, 1, lv.GRID_ALIGN.CENTER, 0, 1)
|
||||
|
||||
# Apply styles on main part and default state
|
||||
label.set_style_bg_opa(lv.OPA._70, 0)
|
||||
label.set_style_bg_color(c1, 0)
|
||||
label.set_style_text_color(c2, 0)
|
||||
label.add_style(style_big_font, 0)
|
||||
|
||||
# Declare an array of strings
|
||||
btnmatrix_options = ["First", "Second", "\n", "Third", ""]
|
||||
|
||||
btnmatrix_ctrl = [lv.buttonmatrix.CTRL.DISABLED,
|
||||
2 | lv.buttonmatrix.CTRL.CHECKED, 1]
|
||||
|
||||
btnmatrix = lv.buttonmatrix(scr)
|
||||
btnmatrix.set_grid_cell(
|
||||
lv.GRID_ALIGN.STRETCH,
|
||||
1,
|
||||
1,
|
||||
lv.GRID_ALIGN.STRETCH,
|
||||
1,
|
||||
1
|
||||
)
|
||||
# Pass string and enum arrays
|
||||
btnmatrix.set_map(btnmatrix_options)
|
||||
btnmatrix.set_ctrl_map(btnmatrix_ctrl)
|
||||
# Add style to non main part and non default state
|
||||
btnmatrix.add_style(style_big_font, lv.PART.ITEMS | lv.STATE.CHECKED)
|
||||
|
||||
btnmatrix.set_selected_button(1)
|
||||
btnmatrix.add_event_cb(
|
||||
lambda _: buttonmatrix_event_cb(btnmatrix, label),
|
||||
lv.EVENT.VALUE_CHANGED,
|
||||
None
|
||||
)
|
||||
btnmatrix.send_event(lv.EVENT.VALUE_CHANGED, None)
|
||||
|
||||
# Create a base object
|
||||
cont = lv.obj(scr)
|
||||
# Span 2 rows
|
||||
cont.set_grid_cell(lv.GRID_ALIGN.STRETCH, 2, 1, lv.GRID_ALIGN.STRETCH, 0, 2)
|
||||
|
||||
# Apply flex layout
|
||||
cont.set_flex_flow(lv.FLEX_FLOW.COLUMN)
|
||||
|
||||
btn1 = list_button_create(cont)
|
||||
btn2 = list_button_create(cont)
|
||||
btn3 = list_button_create(cont)
|
||||
btn4 = list_button_create(cont)
|
||||
btn5 = list_button_create(cont)
|
||||
btn6 = list_button_create(cont)
|
||||
btn7 = list_button_create(cont)
|
||||
btn8 = list_button_create(cont)
|
||||
btn9 = list_button_create(cont)
|
||||
btn10 = list_button_create(cont)
|
||||
|
||||
a = lv.anim_t()
|
||||
a.init()
|
||||
a.set_var(btn1)
|
||||
a.set_values(lv.OPA.COVER, lv.OPA._50)
|
||||
a.set_custom_exec_cb(lambda _, v: opa_anim_cb(btn1, v)) # Pass a callback
|
||||
a.set_time(300)
|
||||
a.set_path_cb(lv.anim_t.path_ease_out)
|
||||
a.start()
|
||||
|
||||
btn2.add_flag(lv.obj.FLAG.HIDDEN)
|
||||
|
||||
btn_label = btn3.get_child(0)
|
||||
btn_label.set_text("A multi-line text with a ° symbol")
|
||||
btn_label.set_width(lv.pct(100))
|
||||
|
||||
a = lv.anim_t()
|
||||
a.init()
|
||||
a.set_var(btn4)
|
||||
a.set_values(lv.OPA.COVER, lv.OPA._50)
|
||||
a.set_custom_exec_cb(lambda _, v: opa_anim_cb(btn4, v)) # Pass a callback
|
||||
a.set_path_cb(lv.anim_t.path_ease_out)
|
||||
a.set_time(300)
|
||||
a.set_repeat_count(lv.ANIM_REPEAT_INFINITE)
|
||||
a.start()
|
||||
|
||||
# Wait and delete the button with the animation
|
||||
|
||||
cont.get_child(3).delete()
|
||||
# Large byte array
|
||||
|
||||
canvas_buf = bytearray(CANVAS_BUF_SIZE(400, 100, 16, 1))
|
||||
|
||||
canvas = lv.canvas(scr)
|
||||
canvas.set_grid_cell(lv.GRID_ALIGN.START, 0, 2, lv.GRID_ALIGN.START, 2, 1)
|
||||
# Test RGB565 rendering
|
||||
canvas.set_buffer(
|
||||
lv.draw_buf_align(canvas_buf, lv.COLOR_FORMAT.RGB565),
|
||||
400,
|
||||
100,
|
||||
lv.COLOR_FORMAT.RGB565
|
||||
)
|
||||
canvas.fill_bg(c2, lv.OPA.COVER)
|
||||
draw_to_canvas(canvas)
|
||||
|
||||
test_img_lvgl_logo_jpg_data = (
|
||||
b'\xFF\xD8\xFF\xE0\x00\x10\x4A\x46\x49\x46\x00\x01\x01\x01\x01\x2C\x01\x2C\x00\x00\xFF\xFE\x00\x13\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x47\x49\x4D\x50\xFF\xDB\x00\x43\x00\x08\x06\x06\x07\x06\x05\x08\x07\x07\x07\x09\x09\x08\x0A\x0C\x15\x0E\x0C\x0B\x0B\x0C\x19\x12\x13\x0F\x15\x1E\x1B\x20\x1F\x1E\x1B\x1D\x1D\x21\x25\x30\x29\x21\x23\x2D\x24\x1D\x1D\x2A\x39\x2A\x2D\x31\x33\x36\x36\x36\x20\x28\x3B\x3F\x3A\x34\x3E\x30\x35\x36\x33\xFF\xDB\x00\x43\x01\x09\x09\x09\x0C\x0B\x0C\x18\x0E\x0E\x18\x33\x22\x1D\x22\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33'
|
||||
b'\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\x33\xFF\xC0\x00\x11\x08\x00\x21\x00\x69\x03\x01\x11\x00\x02\x11\x01\x03\x11\x01\xFF\xC4\x00\x1F\x00\x00\x01\x05\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\xFF\xC4\x00\xB5\x10\x00\x02\x01\x03\x03\x02\x04\x03\x05\x05\x04\x04\x00\x00\x01\x7D\x01\x02\x03\x00\x04\x11\x05\x12\x21\x31\x41\x06\x13\x51\x61\x07\x22\x71\x14\x32\x81\x91\xA1\x08\x23\x42\xB1\xC1\x15\x52\xD1\xF0\x24\x33\x62\x72\x82\x09\x0A\x16\x17\x18\x19\x1A\x25\x26\x27\x28\x29\x2A\x34\x35\x36\x37\x38\x39\x3A\x43\x44\x45\x46\x47\x48\x49\x4A\x53\x54\x55'
|
||||
b'\x56\x57\x58\x59\x5A\x63\x64\x65\x66\x67\x68\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x83\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98\x99\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE1\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xF1\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFF\xC4\x00\x1F\x01\x00\x03\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\xFF\xC4\x00\xB5\x11\x00\x02\x01\x02\x04\x04\x03\x04\x07\x05\x04\x04\x00\x01\x02\x77\x00\x01\x02\x03\x11\x04\x05\x21\x31\x06\x12\x41'
|
||||
b'\x51\x07\x61\x71\x13\x22\x32\x81\x08\x14\x42\x91\xA1\xB1\xC1\x09\x23\x33\x52\xF0\x15\x62\x72\xD1\x0A\x16\x24\x34\xE1\x25\xF1\x17\x18\x19\x1A\x26\x27\x28\x29\x2A\x35\x36\x37\x38\x39\x3A\x43\x44\x45\x46\x47\x48\x49\x4A\x53\x54\x55\x56\x57\x58\x59\x5A\x63\x64\x65\x66\x67\x68\x69\x6A\x73\x74\x75\x76\x77\x78\x79\x7A\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x92\x93\x94\x95\x96\x97\x98\x99\x9A\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xC2\xC3\xC4\xC5\xC6\xC7\xC8\xC9\xCA\xD2\xD3\xD4\xD5\xD6\xD7\xD8\xD9\xDA\xE2\xE3\xE4\xE5\xE6\xE7\xE8\xE9\xEA\xF2\xF3\xF4\xF5\xF6\xF7\xF8\xF9\xFA\xFF\xDA\x00\x0C\x03\x01\x00\x02\x11\x03'
|
||||
b'\x11\x00\x3F\x00\x4F\x11\xFC\x6B\xF1\x25\x8F\x89\x35\x2B\x2B\x2B\x7B\x04\xB7\xB6\xB9\x78\x50\x49\x13\x33\x10\xAC\x57\x24\xEE\x1D\x71\x9A\x00\xCB\xFF\x00\x85\xEB\xE2\xEF\xF9\xE7\xA6\xFF\x00\xDF\x86\xFF\x00\xE2\xA9\x88\xD7\xF0\xE7\xC5\x5F\x1B\xF8\x9B\x57\x5D\x36\xD6\x4D\x0E\x09\x59\x19\xC3\xDC\xC6\xC8\xB8\x03\x3D\x77\x1E\x69\x0C\xF5\x4F\x87\xFE\x25\xBB\xF1\x4F\x84\xE3\xD4\x6F\xA3\x85\x2E\x44\xAF\x14\x9E\x47\xDC\x62\xA7\x19\x1C\x9A\x00\xD7\xD0\xB5\xBB\x5F\x11\x69\x11\x6A\x56\x42\x41\x04\x8C\xCA\xA2\x45\xC3\x65\x58\xA9\xE3\xEA\x0D\x00\x26\xB9\xAE\xDA\x78\x7A\xCE\x2B\xBB\xE1\x20\xB7\x79\xD2\x16\x91\x14\x11\x19\x63\x80\xCD\xCF\x0B\x9C\x73'
|
||||
b'\xEF\x40\x1A\x74\x01\x43\x5A\xD6\x2D\x34\x0D\x22\xE3\x53\xBE\x66\x10\x42\x01\x21\x46\x59\x89\x38\x00\x0E\xE4\x92\x00\x14\x00\xEB\xCD\x56\xCF\x4D\xD3\x0E\xA3\xA8\xCE\xB6\x76\xEA\xA1\x9D\xA7\x21\x76\xE7\xB1\xF7\xF6\x14\x01\xCE\xAF\xC4\x0B\x69\xD7\xCD\xB4\xD0\x7C\x43\x75\x6D\xD4\x5C\x45\xA7\xB6\xC2\x3D\x40\x24\x12\x3E\x82\x80\x36\xB4\x4F\x11\xE9\x7E\x21\x8A\x47\xD3\xEE\x0B\x3C\x27\x6C\xD0\xC8\x86\x39\x62\x3E\x8C\x8D\x82\x28\x01\xE9\xAD\xDA\xC9\xE2\x29\xB4\x35\x12\x7D\xAE\x2B\x65\xB9\x63\xB7\xE5\xD8\x58\xA8\xE7\xD7\x20\xD0\x06\x95\x00\x14\x01\xF3\x87\x88\x6F\x3C\x26\x3C\x49\xAA\x09\xFC\x20\x25\x98\x5D\xCA\x1E\x4F\xED\x29\x57\x7B\x6F\x39'
|
||||
b'\x38\x1C\x0C\x9E\x71\x5C\x13\xC6\xB8\xC9\xAB\x6C\x7D\x66\x1F\x86\x63\x56\x94\x6A\x7B\x4B\x5D\x27\xB7\x75\xEA\x72\x3E\x3C\xD2\xAC\xB4\x5F\x18\xDE\xD8\xE9\xD1\x34\x56\x88\x23\x68\xE3\x67\x2D\xB7\x74\x6A\xC4\x64\xF2\x79\x26\xBB\xD3\xBA\x3E\x52\x4B\x96\x4D\x1C\xE5\x32\x4F\xA6\x7E\x09\x7F\xC9\x37\x8F\xFE\xBE\x65\xFE\x62\x90\xCD\x4F\x85\x5F\xF2\x4F\x6C\x7F\xEB\xB4\xFF\x00\xFA\x39\xE8\x03\xA4\xD6\xB4\xAB\x7D\x73\x44\xBC\xD2\xEE\x86\x61\xBA\x89\xA3\x6F\x6C\xF4\x23\xDC\x1C\x1F\xC2\x80\x31\xBC\x05\xAA\xDC\x6A\x1E\x1C\x16\x97\xE7\xFE\x26\x7A\x64\x8D\x65\x76\x0F\x52\xE9\xC0\x6F\xF8\x12\xE0\xFE\x34\x01\x4F\x5C\xFF\x00\x8A\x8B\xC7\x3A\x66\x82\xBF'
|
||||
b'\x35\x9E\x98\x06\xA1\x7D\xE8\x5F\xA4\x28\x7F\x1C\xB6\x3D\x85\x00\x45\x35\xB4\x7E\x27\xF8\x9F\x3D\xB5\xE8\x12\xD8\xE8\x16\xF1\x49\x1D\xBB\x0C\xAB\x5C\x49\x92\x1C\x8E\xFB\x54\x71\xE8\x4D\x00\x77\x34\x01\x02\x2D\xAA\xDE\x4A\xD1\xAC\x22\xE5\x95\x7C\xD2\xB8\xDE\x40\xE9\x9E\xF8\xE4\xE2\x80\x39\x3B\x5F\xF9\x2C\x7A\x87\xFD\x81\x61\xFF\x00\xD1\xAD\x40\x1D\x9D\x00\x14\x01\xF3\xC6\xBD\xFF\x00\x08\x5F\xFC\x24\x5A\x9F\xDA\x06\xBF\xE7\xFD\xAE\x5F\x33\xCB\x30\xED\xDD\xBC\xE7\x19\xE7\x19\xAF\x26\xA7\xB1\xE7\x77\xBF\xE0\x7E\x87\x83\xFE\xD2\xFA\xBD\x3E\x4E\x4B\x59\x5A\xFC\xD7\xB5\x89\xBC\x79\x61\xE0\xC9\xBC\x5D\x73\x26\xA0\x75\xE1\x72\x63\x8B\x7F\xD9'
|
||||
b'\xCC\x3B\x31\xE5\xAE\x31\xBB\x9E\x98\xCF\xBD\x76\x4F\x15\x0A\x6F\x95\xA3\xE6\xB0\xD9\x0E\x23\x17\x4F\xDB\x46\x49\x27\x7E\xFD\xFD\x0E\x1B\xC6\x7A\x06\x9D\xA1\x5D\x69\xAD\xA5\xCD\x75\x25\xA5\xF5\x92\xDC\xA8\xBA\xDB\xBD\x72\xCC\x30\x76\xF1\xFC\x35\xD3\x09\x29\xC5\x49\x1E\x3E\x26\x84\xB0\xF5\x65\x4A\x5B\xA7\x63\xDC\xFE\x09\x7F\xC9\x37\x8F\xFE\xBE\x65\xFE\x62\x99\x89\xA1\xF0\xB2\x68\x93\xE1\xFD\x92\xB4\xA8\x0F\x9D\x3F\x05\x87\xFC\xF6\x7A\x00\xED\x16\x68\x9D\xB6\xAC\x88\xC7\xD0\x30\x34\x01\xC2\x6B\x97\x90\x78\x27\xC7\x2B\xAE\x5C\x37\x95\xA4\xEB\x10\x18\x6E\xDB\xB2\x4F\x1A\x96\x46\xFA\xB2\x82\xBF\x80\xA0\x0D\x3F\x00\xD9\x4E\x34\x79\xB5\xBB'
|
||||
b'\xF4\x2B\xA8\x6B\x33\x1B\xB9\x41\xEA\x88\x78\x8D\x3F\xE0\x29\x8F\xCC\xD0\x05\x1D\x66\x56\xF0\x87\x8D\x9B\xC4\x73\x46\xCD\xA3\x6A\x50\x25\xBD\xF4\xA8\xA5\x8D\xBC\x88\x4E\xC9\x1B\x1F\xC2\x41\x20\x9E\xD4\x01\xD8\x5B\x6A\x36\x37\x96\xCB\x73\x6D\x79\x04\xD0\x30\xC8\x92\x39\x03\x29\x1F\x51\x40\x1C\x96\x83\x79\x6D\xA8\x7C\x4D\xF1\x0D\xC5\x9C\xF1\xDC\x40\x96\x56\xD1\x34\x91\x36\xE5\x0E\x0B\xE5\x72\x38\xC8\xC8\xE2\x80\x16\x09\x12\x3F\x8C\x5A\x81\x77\x55\x1F\xD8\xB0\xF5\x38\xFF\x00\x96\xAD\x40\x1D\x8F\xDA\x20\xFF\x00\x9E\xD1\xFF\x00\xDF\x42\x80\x1D\xBD\x3F\xBE\xBF\x9D\x00\x79\x46\xA9\xF0\x6A\x6D\x47\x56\xBC\xBD\x1A\xDA\x20\xB8\x9D\xE5\x08\x6D'
|
||||
b'\x89\xDB\xB9\x89\xC6\x77\x7B\xD7\x04\xF0\x5C\xD2\x6F\x98\xFA\xCC\x3F\x13\x46\x95\x28\xD3\xF6\x57\xB2\x4B\x7E\xCB\xD0\xB7\xE2\x3F\x84\xD2\xEB\xDA\xDC\xBA\x82\xEB\x09\x08\x91\x11\x76\x1B\x72\xD8\xDA\x81\x7A\xEE\xF6\xAA\xAB\x84\xE7\x97\x35\xCC\x70\x3C\x42\xB0\xB4\x15\x2F\x67\x7B\x5F\xAF\x77\x7E\xC5\x4F\x12\x7C\x1A\x97\x5E\x8F\x49\x55\xD6\xD2\x13\x61\x64\xB6\xA4\x9B\x62\xDB\xF0\xCC\x77\x7D\xEE\x3E\xF7\x4A\xEA\xA7\x1E\x48\xA8\xF6\x3C\x1C\x5D\x7F\xAC\x57\x9D\x5B\x5B\x99\xDC\xEE\x3C\x15\xE1\x64\xF0\x7F\x86\x61\xD2\x16\xE4\xDC\x95\x66\x77\x94\xAE\xDD\xC5\x8F\x61\x93\x81\x56\x73\x91\x37\xC3\xCF\x08\x33\x16\x6F\x0F\x58\x12\x4E\x49\x31\x75\xA0'
|
||||
b'\x0B\x7A\x6F\x83\xFC\x3B\xA3\xDE\xAD\xE6\x9D\xA3\xDA\x5A\xDC\xA8\x20\x49\x12\x60\x80\x7A\xD0\x05\xFD\x4F\x4A\xB0\xD6\x6C\xCD\xA6\xA5\x69\x15\xD5\xB9\x60\xC6\x39\x57\x23\x23\xA1\xA0\x0B\x6A\xA1\x54\x2A\x80\x00\x18\x00\x76\xA0\x01\x95\x5D\x4A\xB2\x86\x52\x30\x41\x19\x06\x80\x39\xB9\xBE\x1E\xF8\x42\x79\xCC\xD2\x78\x7A\xC3\x79\x39\x38\x88\x00\x4F\xD0\x71\x40\x1B\xB6\x56\x16\x9A\x6D\xAA\xDB\x58\xDA\xC3\x6D\x02\x7D\xD8\xE1\x40\x8A\x3F\x01\x40\x19\xDA\xA7\x84\xBC\x3F\xAD\xDD\x8B\xBD\x4F\x49\xB5\xBB\xB8\x0A\x10\x49\x2A\x64\xED\x1D\x07\xEA\x68\x02\x8F\xFC\x2B\xBF\x07\xFF\x00\xD0\xBB\x61\xFF\x00\x7E\xA8\x03\x73\xFB\x32\xCB\xFE\x7D\xD2\x80\x2D'
|
||||
b'\xD0\x01\x40\x05\x00\x14\x00\x50\x01\x40\x05\x00\x14\x00\x50\x01\x40\x05\x00\x14\x00\x50\x01\x40\x1F\xFF\xD9'
|
||||
)
|
||||
|
||||
test_img_lvgl_logo_jpg = lv.image_dsc_t(
|
||||
dict(
|
||||
header=dict(cf=lv.COLOR_FORMAT.RAW_ALPHA, w=105, h=33),
|
||||
data_size=1947,
|
||||
data=test_img_lvgl_logo_jpg_data
|
||||
)
|
||||
)
|
||||
|
||||
img = lv.image(scr)
|
||||
img.set_src(test_img_lvgl_logo_jpg)
|
||||
img.align(lv.ALIGN.BOTTOM_RIGHT, -20, -20)
|
||||
img.add_flag(lv.obj.FLAG.IGNORE_LAYOUT)
|
||||
|
||||
img = lv.image(scr)
|
||||
img.set_src("A:test_img_lvgl_logo.png")
|
||||
img.set_pos(500, 420)
|
||||
img.add_flag(lv.obj.FLAG.IGNORE_LAYOUT)
|
||||
img.set_rotation(200)
|
||||
img.set_scale_x(400)
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def chart_type_observer_cb(chart, subject):
|
||||
v = subject.get_int()
|
||||
# chart = observer.get_target()
|
||||
chart.set_type(lv.chart.TYPE.LINE if v == 0 else lv.chart.TYPE.BAR)
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def buttonmatrix_event_cb(buttonmatrix, label):
|
||||
# label = e.get_user_data()
|
||||
# buttonmatrix = e.get_target()
|
||||
idx = buttonmatrix.get_selected_button()
|
||||
text = buttonmatrix.get_button_text(idx)
|
||||
label.set_text(text)
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def list_button_create(parent):
|
||||
btn = lv.button(parent)
|
||||
btn.set_size(lv.pct(100), lv.SIZE_CONTENT)
|
||||
|
||||
# Get an integer
|
||||
idx = btn.get_index()
|
||||
|
||||
# Formatted string for label
|
||||
label = lv.label(btn)
|
||||
label.set_text(lv.SYMBOL.FILE + " Item %d" % idx)
|
||||
|
||||
return btn
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def opa_anim_cb(button, value):
|
||||
try:
|
||||
button.set_style_opa(value, 0)
|
||||
except: # NOQA
|
||||
pass
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def draw_to_canvas(canvas):
|
||||
layer = lv.layer_t()
|
||||
canvas.init_layer(layer)
|
||||
|
||||
# Use draw descriptors
|
||||
|
||||
test_img_lvgl_logo_png_data = (
|
||||
b'\x89\x50\x4E\x47\x0D\x0A\x1A\x0A\x00\x00\x00\x0D\x49\x48\x44\x52\x00\x00\x00\x69\x00\x00\x00\x21\x08\x06\x00\x00\x00\xDA\x89\x85\x3B\x00\x00\x00\x06\x62\x4B\x47\x44\x00\x00\x00\x00\x00\x00\xF9\x43\xBB\x7F\x00\x00\x00\x09\x70\x48\x59\x73\x00\x00\x2E\x23\x00\x00\x2E\x23\x01\x78\xA5\x3F\x76\x00\x00\x00\x07\x74\x49\x4D\x45\x07\xE7\x09\x12\x12\x25\x07\x59\xA0\x4E\xA5\x00\x00\x00\x19\x74\x45\x58\x74\x43\x6F\x6D\x6D\x65\x6E\x74\x00\x43\x72\x65\x61\x74\x65\x64\x20\x77\x69\x74\x68\x20\x47\x49\x4D\x50\x57\x81\x0E\x17\x00\x00\x06\xB9\x49\x44\x41\x54\x68\xDE\xED\x9A\x7F\x8C\x5D\x45\x15\xC7\x3F\xE7\xBE\xF7\x76\xA9\x20\x18\x03\x9A\x6A\x77\xE6\xDD'
|
||||
b'\xB7\x6B\x8A\x49\xC3\x1A\xB5\x25\x80\xB5\xE2\x6A\x2B\x0D\x46\x71\x89\x8A\xBF\x48\x4C\xD5\xD4\x46\x08\x58\x48\x10\xC5\xE8\x3F\xA6\x68\x6B\xE4\x0F\x85\x22\x68\x53\x6D\x9A\x40\x31\x40\xC0\x92\xB6\xD0\x62\x53\x4A\xAC\x44\xA2\xAD\xA4\x76\xF7\xDE\xB9\xAF\x3F\x0C\x0A\xD2\x96\x6D\xD9\xDD\xB7\xF7\xF8\xC7\x9B\xCA\x76\xF7\xFD\x5C\x77\xDD\xD7\xE4\x7D\x93\x97\x97\xB9\x33\x77\x66\xCE\xF9\xCE\x39\x73\xE6\xCC\x85\x36\xDA\x68\xE3\x7F\x87\x00\x98\x7C\xBE\x13\x95\xE5\x40\x0F\x5A\x7E\x36\x8D\x23\x0C\xA1\x6C\x4D\x92\x68\xA0\xAD\xEE\x29\xAA\xD0\x5A\x13\x28\x99\xCD\xC0\xF5\x67\x48\x9B\x01\x9C\x00\x96\x26\x2E\x7A\xBE\xAD\xF2\xE6\x91\x85\xCC\x42\xA0\x7F\x06'
|
||||
b'\x08\x2A\x01\x81\xFF\x5D\x08\xDC\x02\x7C\x7E\x7C\x83\xAE\xAE\x82\x48\xA0\x9D\x80\x04\xA2\xC3\x71\x1C\xA7\xF5\x3A\x35\xB6\x90\x45\x35\x07\x68\x92\x44\x6F\x4C\x75\x72\xF3\xC2\x30\x08\x52\x3A\x01\x4D\x5C\xFD\x7E\xAC\x0D\x73\xAA\xBC\x05\xD1\x9C\x57\xD5\x88\xA2\xA7\x8B\x2E\x1E\x6D\x64\x3C\x6B\x0B\x19\x55\xED\x40\x34\x4D\x5C\x3C\xDC\xCC\x5C\x03\x85\x8B\xBD\x22\xA7\x13\x03\xC0\xE5\xC0\xA7\x80\xD3\xFE\xD9\x3B\x27\x99\xB1\xF0\x56\xE0\x79\xE0\x40\xAA\xD2\xDB\x58\xD7\xDA\x8B\xB0\x1F\xE1\xAF\xC6\x86\xF3\xA7\xEC\x42\x52\xBE\x08\xBC\x04\x3C\x62\xF2\x85\x6C\x45\x22\x4D\x3E\x6B\x6C\xF8\x31\x63\xC3\x5F\x2B\xBC\x88\x30\x08\x52\x04\x8A\xC0\xA0\x20\x7F'
|
||||
b'\x36\x36\x7C\xC0\xD8\x70\x89\xC9\x87\x99\x9A\xB3\x46\xAF\x43\x78\x09\xE4\x31\x63\xC3\x6C\x53\x24\xCD\x90\x85\x3E\x9B\xB8\xE8\x05\xA1\xF4\x24\x70\xAC\xCE\xF8\xEF\x06\x8C\x22\xB9\x86\x28\x4A\xF5\x45\xE0\x35\xA0\x1B\x58\x31\x95\xC9\x19\x53\xC8\x08\x7C\x0B\x30\xC0\x13\x49\x3C\x58\x9A\x68\xE1\xC6\x86\x57\x07\x22\x7B\x80\x6D\xC0\x8D\xC0\x7C\x20\x07\xFC\xC3\xCB\x94\xF5\xCF\xBE\x0A\xEC\x44\x79\xDA\xD8\xB0\xD6\x42\x9B\xE3\xC7\x9B\xAB\xA2\xB4\x02\x49\xFD\xC6\x86\xB7\x2B\xD9\xB5\x80\x9D\xCE\x8E\x8B\xC5\xB8\x04\xFC\xD8\x17\x57\xD8\x7C\x78\x49\xB3\x7D\xA8\x68\x1F\xB0\x10\x38\x26\xE8\x86\xB3\x09\xCC\x8B\x04\x7A\x07\xF0\xD4\x99\x36\xC0\xF7\x80\x45'
|
||||
b'\x88\xBE\x23\x71\x51\x98\xB8\xA8\xA0\xA2\x97\x80\xF6\x02\xB7\x01\x09\xF0\x61\xE0\x59\x63\xC3\x65\x33\xB0\x27\xCD\x08\x2E\x04\xD6\xCC\xD8\x4E\xAA\x3C\x86\x10\x03\x79\x55\xBE\x0C\xAC\x6B\xF4\x55\x6B\xC3\x40\xE1\x26\x5F\x7C\xD0\xB9\xF8\xF5\x71\xFB\x94\x90\xF2\x5D\xE0\x87\x80\x02\xBF\x50\xE1\x8E\x62\x1C\x1D\x9F\xB4\x58\xE2\x78\x14\xD8\x0F\xEC\x37\xA6\x70\x1F\xA2\x6B\x80\x65\x40\x34\xDD\xE2\x06\xC0\xCB\x40\xCA\x39\x84\x24\x89\x86\x80\xFB\x7D\x71\xA5\xB5\xB6\xA3\x71\x7E\xB9\xD4\x2B\xF3\x34\x70\xEF\x59\xCA\x48\xE9\x03\xEE\xF2\xC5\xEF\xA8\xE8\xAA\x4A\x04\x4D\x9E\xCF\xE0\x49\x90\x55\x22\xB2\x30\x71\xD1\xC1\x69\xB7\xA4\x4C\x90\xEE\x2B\x8D\x05'
|
||||
b'\xBD\x12\xC8\xDC\x2A\x62\x65\x51\xBE\x06\x5C\xD7\x4A\x44\xA9\x72\x9F\x08\xAB\x81\x1E\x25\xB8\x1E\xD8\xD4\xE0\xAB\xAB\xBD\x07\xD9\x90\xB8\xE8\xF0\x9B\x51\xA3\xED\x04\xD6\xFA\xBA\x8D\x28\x6B\x8A\x2E\x6E\x78\xF3\x48\xDC\xA0\x02\xAF\xCE\x48\x08\xBE\x35\x72\x73\xB4\x1C\x89\x9D\x57\x79\xE1\xF1\xF8\x52\x1B\xFE\xC0\x47\x6A\x41\xAB\x90\x54\x4C\xA2\x57\x8C\x0D\x37\x03\x2B\x81\x6F\x74\xF7\xBC\x67\xF3\xC0\xA1\xBF\xA7\xB5\xC3\xF7\xF0\x5D\xFE\xB8\x51\x9A\x68\x45\x10\x7C\x04\xB8\x0C\x18\x42\xB9\x33\x49\x22\x6D\x15\x59\xB3\x0A\x4B\x80\x5F\xD6\x68\x93\x57\xD8\x20\x65\xC2\x5A\x0D\x3F\xF5\x11\xDE\xE2\xD1\x91\xD2\x95\xC0\xEE\x3A\xED\xBF\xEE\xF7\xCB\xA7'
|
||||
b'\x12\x17\xED\x9B\x50\xF7\x05\xFF\xFF\x50\x92\x44\xC5\x56\x12\x32\x68\xC0\x3A\x02\x5A\x15\x2A\x87\x80\x47\x01\x41\xB8\x79\x5E\x97\x91\x1A\x01\xC3\x45\x9E\xA4\x14\xF8\xD9\xF8\xBA\x8B\xBB\x17\x08\xB0\xC8\x17\x9F\x6E\x35\x31\x5B\x97\x80\x86\x02\x88\x41\x05\x7E\xEE\xDD\xF2\xB5\x22\xD9\x7C\x8D\x80\xA1\x1F\x98\x0B\xFC\x2D\x95\x74\xFB\xF8\xBA\xF3\x4B\xA7\x2E\xA0\x7C\xA8\x4F\x81\x43\x6D\x92\xA6\x19\x63\xA3\x23\x3B\x81\xE7\x80\xF3\x44\xF4\x96\x4A\x6D\xBA\x0A\x61\xCE\x07\x0C\x00\x6B\x0F\xC7\xEE\xAC\x54\x4E\x0A\x19\xAF\x0B\x05\x86\xA7\x32\x0F\x63\xC3\x15\xC6\x86\x1B\x8D\x0D\xFB\xDB\x24\x4D\xC0\x91\xA3\x47\xC6\x5B\xD3\x0D\xC6\x16\xDE\x3E\x29\x05'
|
||||
b'\x34\xC6\x32\x9F\x1D\x38\x2A\x2A\x5B\x26\xD6\x67\x44\x87\x81\x51\xAF\x8F\x8B\xA6\x38\x95\xCB\x81\x2F\xF9\xE0\xA3\x4D\xD2\x24\x12\x08\xB6\x00\xAE\xEC\xB2\xF4\xC6\x0A\x4D\x6E\xF2\xB2\xAE\x77\xC9\xE0\x89\x89\x95\x71\x1C\x9D\xF6\xEF\x0B\xB0\xA0\x15\xDD\x5D\xBD\x2C\xEE\x28\xC2\x49\x60\xA4\x55\x49\x72\x6E\xE0\x8D\x71\xC1\xC0\x2A\x6B\xED\x9C\x71\x6E\x68\x11\xF0\x51\xE0\x84\x0A\xEB\x6B\x74\xF3\x8C\xFF\xFF\x4C\xAB\xC9\x97\x55\x78\x46\xE0\x9A\x2A\xE7\xA4\x14\xF8\x83\xA0\xAF\x81\x5C\xA1\x10\x56\x5E\xC9\x04\x94\xEF\xA3\x6E\x98\xC5\x48\x6F\x13\xA2\xDF\x07\x0A\x4A\x70\x0D\xF0\xC8\x99\x8C\x04\xE5\x3D\x67\x4B\x31\x8E\x8E\xD5\x48\x45\xFC\x06\xE1\x56'
|
||||
b'\x60\xB1\xB1\xE1\x92\xC4\x45\xBB\x5A\x86\xA4\x71\x7E\x78\x4E\x25\x92\x14\x3A\xB6\xC7\x71\x90\x96\x09\x7A\x5B\x95\x03\xEF\xAE\x3E\xD3\xBD\x2B\x23\x69\x3F\xD0\x31\x1B\x82\x24\xC9\xE0\xCB\xC6\x86\x0F\x00\xDF\x06\x6E\xEB\xE9\x9E\xFF\xBB\xE1\xD2\x48\x17\xE5\x3B\xAC\x12\xF0\x93\x9A\x2E\x25\xE0\x40\xAA\x3C\x01\x7C\x1A\xB8\xA7\xCB\x14\x16\x17\x2B\xB8\xC6\x59\x21\x49\xE0\x6A\x60\x73\x75\x7F\xCF\xDD\x29\xFC\x0A\x78\xD8\xAF\xC8\x4A\xD8\x74\xA4\x23\xB3\xD2\x8C\xA6\xB3\x9B\x03\x54\xD6\x23\x7C\x13\x58\x38\x52\x1A\xB9\x4A\xE0\x5A\xEF\x21\x9E\x94\xF2\xDD\x51\x55\xC4\x71\x94\x5A\x1B\xDE\xAC\x70\x25\x70\x99\x88\x3E\x64\x6C\xFE\xB3\x89\x8B\x8F\xCF\x36'
|
||||
b'\x49\x41\x0D\xC5\xBF\x19\xFC\xD4\x6F\x93\x6D\x85\x15\x97\x24\xD1\x41\x60\xAB\x97\xE9\x76\xE0\x2B\xBE\xEA\x1E\xE7\xA2\xBA\x0B\xC8\xB9\x28\x01\x3E\x07\x9C\x04\x96\x82\x3C\x67\x6C\xD8\x67\x4C\x4F\xA6\x7A\xE8\x5D\x08\x8C\x0D\xDF\x0F\x7C\x68\x26\xDD\x5D\x4B\x04\x68\x82\x5E\x65\x6C\xBE\xD1\xBB\xA1\xE3\x89\x8B\x77\x57\xB1\xFC\x35\x5A\xCE\x33\x7E\xD2\x3F\xDA\x97\xCB\xE5\xB6\x37\x4C\xB4\x8B\x76\x1A\x1B\x2E\x05\x7E\x0B\xBC\x17\xD8\x86\x8C\xED\x35\x36\xFC\x3D\xC8\x1F\x11\x2D\xA2\xAA\xA8\xCC\x45\x78\x1F\xE8\xC7\x81\x3E\xAF\xCB\x18\x78\xBC\xCE\x10\x17\x88\xB2\xDC\xD8\xFC\x58\x63\xCE\x41\x0E\xB4\x0C\x49\xC0\xBA\x26\x3E\xB3\x78\x01\xF8\x40\x15\xA9'
|
||||
b'\xFE\x84\xB0\x97\xB2\xDB\x02\xB8\x77\xE0\xD0\xC1\xB1\xA6\x2C\xD2\x45\x7B\x4D\x3E\xFC\x20\xCA\x6A\x9F\x4A\xBA\xA2\xFC\x53\x9F\xC1\x94\x89\x53\xFD\x27\x70\xBF\x90\xAE\x73\xCE\xBD\x52\xA7\xFB\x10\xE4\xD1\x26\x14\x73\x6B\x76\x76\xCD\x27\x1D\x51\x64\x23\x70\x7E\x93\xAF\x56\x4D\x80\xBA\x24\x2A\x19\x1B\xDE\xE5\xDD\x56\x49\x48\x37\x4D\xC9\x75\xC6\xD1\xBF\x81\x3B\x8D\xC9\xFF\x08\x91\x4F\x78\xA2\x7A\x7C\x90\x75\xE6\x5A\x62\x00\xD8\x13\x08\xDB\xE2\x38\x1A\xAA\x63\x12\x03\xC8\x7F\xEF\xC0\x9A\x59\xBD\x7F\xF9\x7F\x92\x94\x4C\xDE\x03\xE2\x53\x94\xBF\x22\x9A\xDE\x81\x5C\xB4\x03\xD8\x31\x3D\xFB\x5C\xFC\xBA\x0F\x9A\x1E\x9E\x37\x2F\x94\x20\x53\x3E\x99'
|
||||
b'\x24\xCE\x69\x73\xFD\x44\x7B\x80\x3D\x53\xDD\x93\x4A\xF5\xD2\x63\x0A\xF5\xDC\x45\x89\x52\xA9\x04\x0C\x55\x39\x6F\x1D\x05\xEE\x3E\xD7\x33\x1B\x87\x0F\xCF\xCE\x1D\x93\x1C\x84\xCE\xB4\xBC\xC9\x76\x56\x39\x03\xED\x50\xF8\x97\xC0\x72\xCA\x77\x31\x95\xB0\xFB\x52\x70\xC6\xE4\x7B\x09\x64\xC1\x84\x1E\x4E\x29\xEC\x2A\xBA\xE8\x55\xDA\x68\xA3\x8D\x36\xDA\x68\xA3\x8D\x73\x1A\xFF\x01\xC1\xBA\x4F\x53\x6B\xDA\x6F\x58\x00\x00\x00\x00\x49\x45\x4E\x44\xAE\x42\x60\x82'
|
||||
)
|
||||
|
||||
test_img_lvgl_logo_png = lv.image_dsc_t(
|
||||
dict(
|
||||
header=dict(cf=lv.COLOR_FORMAT.RAW_ALPHA, w=105, h=33),
|
||||
data_size=1873,
|
||||
data=test_img_lvgl_logo_png_data
|
||||
)
|
||||
)
|
||||
|
||||
image_draw_dsc = lv.draw_image_dsc_t()
|
||||
|
||||
image_draw_dsc.init()
|
||||
image_draw_dsc.src = test_img_lvgl_logo_png
|
||||
|
||||
coords = lv.area_t(
|
||||
dict(
|
||||
x1=10,
|
||||
y1=10,
|
||||
x2=10 + test_img_lvgl_logo_png.header.w - 1,
|
||||
y2=10 + test_img_lvgl_logo_png.header.h - 1
|
||||
)
|
||||
)
|
||||
lv.draw_image(layer, image_draw_dsc, coords)
|
||||
|
||||
# Reuse the draw descriptor
|
||||
coords.move(40, 40)
|
||||
image_draw_dsc.opa = lv.OPA._50
|
||||
lv.draw_image(layer, image_draw_dsc, coords)
|
||||
|
||||
line_draw_dsc = lv.draw_line_dsc_t()
|
||||
line_draw_dsc.init()
|
||||
line_draw_dsc.color = lv.color_hex3(0xCA8)
|
||||
line_draw_dsc.width = 8
|
||||
line_draw_dsc.round_end = 1
|
||||
line_draw_dsc.round_start = 1
|
||||
line_draw_dsc.p1.x = 150
|
||||
line_draw_dsc.p1.y = 30
|
||||
line_draw_dsc.p2.x = 350
|
||||
line_draw_dsc.p2.y = 55
|
||||
lv.draw_line(layer, line_draw_dsc)
|
||||
|
||||
canvas.finish_layer(layer)
|
||||
|
||||
c = lv.color_hex(0xff0000)
|
||||
for i in range(50):
|
||||
canvas.set_px(100 + i * 2, 10, c, lv.OPA.COVER)
|
||||
|
||||
|
||||
@test_func_wrapper
|
||||
def main():
|
||||
lv.tick_inc(300)
|
||||
lv.refr_now(None)
|
||||
|
||||
|
||||
create_ui()
|
||||
main()
|
||||
# end
|
BIN
tests/micropy_test/test_img_lvgl_logo.png
Normal file
BIN
tests/micropy_test/test_img_lvgl_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
Loading…
x
Reference in New Issue
Block a user