From 7766bd6bd7c676bf4e31970b04d08cc61e7cf6a9 Mon Sep 17 00:00:00 2001 From: Yann MAGNIN Date: Thu, 11 May 2023 19:01:27 +0200 Subject: [PATCH] vxSDK - 0.12.0-42 : remove assets converter and project module *update* > [vxsdk] | [conv] remove converter module | [project] remove project module *fix* > [install] | allow force install (useful when python major version update break pip env) --- assets/project/.gitignore | 13 - assets/project/Makefile | 92 ------ assets/project/src/main.c | 14 - assets/project/vxsdk.toml | 8 - install.sh | 39 +-- vxsdk/cli/conv/__init__.py | 65 ----- vxsdk/cli/conv/addin.py | 69 ----- vxsdk/cli/conv/assets.py | 75 ----- vxsdk/cli/conv/doctor.py | 24 -- vxsdk/cli/project.py | 54 ---- vxsdk/core/build/compile.py | 23 +- vxsdk/core/conv/__init__.py | 72 ----- vxsdk/core/conv/addin.py | 67 ----- vxsdk/core/conv/assets.py | 132 --------- vxsdk/core/conv/pixel.py | 45 --- vxsdk/core/conv/type/__init__.py | 0 vxsdk/core/conv/type/font.py | 468 ------------------------------- vxsdk/core/conv/type/image.py | 403 -------------------------- vxsdk/core/project/__init__.py | 17 -- vxsdk/core/project/new.py | 29 -- 20 files changed, 24 insertions(+), 1685 deletions(-) delete mode 100644 assets/project/.gitignore delete mode 100644 assets/project/Makefile delete mode 100644 assets/project/src/main.c delete mode 100644 assets/project/vxsdk.toml delete mode 100644 vxsdk/cli/conv/__init__.py delete mode 100644 vxsdk/cli/conv/addin.py delete mode 100644 vxsdk/cli/conv/assets.py delete mode 100644 vxsdk/cli/conv/doctor.py delete mode 100644 vxsdk/cli/project.py delete mode 100644 vxsdk/core/conv/__init__.py delete mode 100644 vxsdk/core/conv/addin.py delete mode 100644 vxsdk/core/conv/assets.py delete mode 100644 vxsdk/core/conv/pixel.py delete mode 100644 vxsdk/core/conv/type/__init__.py delete mode 100644 vxsdk/core/conv/type/font.py delete mode 100644 vxsdk/core/conv/type/image.py delete mode 100644 vxsdk/core/project/__init__.py delete mode 100644 vxsdk/core/project/new.py diff --git a/assets/project/.gitignore b/assets/project/.gitignore deleted file mode 100644 index 2c4f84b..0000000 --- a/assets/project/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -# Build files -/build-fx -/build-cg -/*.g1a -/*.g3a - -# Python bytecode - __pycache__/ - -# Common IDE files -*.sublime-project -*.sublime-workspace -.vscode diff --git a/assets/project/Makefile b/assets/project/Makefile deleted file mode 100644 index 0e25e74..0000000 --- a/assets/project/Makefile +++ /dev/null @@ -1,92 +0,0 @@ -#! /usr/bin/make -f - - -# -# variable definition -# - -# color definition, for swagg :D -red := \033[1;31m -green := \033[1;32m -blue := \033[1;34m -white := \033[1;37m -nocolor := \033[1;0m - -src := $(foreach path,\ - $(shell find src -not -path "*/\.*" -type d), \ - $(wildcard $(path)/*.c) \ - $(wildcard $(path)/*.S) \ - $(wildcard $(path)/*.s)) - -obj := $(patsubst src_%,$(VXSDK_PREFIX_BUILD)/%.o,$(subst /,_,$(src))) -obj += $(patsubst \ - $(VXSDK_ASSETS_SRC)/%,\ - $(VXSDK_ASSETS_BUILD)/%.o,\ - $(wildcard $(VXSDK_ASSETS_SRC)/*.c) \ - ) - -cflags := -ffreestanding -nostdlib -m4-nofpu -fPIE -O1 -cflags += -mb -fstrict-volatile-bitfields -cflags += $(VXSDK_CFLAGS_INCLUDE) -I.. -Iinclude - -# debug vars -VERBOSE ?= false - -# -# build rules -# - -vxaddin: $(obj) - @ printf "$(blue)Create $(red)$@$(nocolor)\n" - sh-elf-vhex-gcc \ - -T $(VXSDK_PREFIX_LIB)/fxcg50-dynamic.ld -Wl,-q -Wl,-M \ - $(VXSDK_CFLAGS_LINK) \ - -o $@ $^ \ - -lvhex-fxcg50 -lc -lgcc \ - > $(VXSDK_PREFIX_BUILD)/map.txt - vxsdk conv addin -b $@ -n vxaddin -o /tmp/vxaddin - -version: - @echo "$(VXSDK_PKG_VERSION)" - -help: - @ echo 'Rules listing:' - @ echo '... all the default, if no target is provided' - @ echo '... clean remove build object' - @ echo '... fclean remove all generated object' - @ echo '... re same as `make fclean all`' - @ echo '... version display version' - @ echo '... install install the library' - @ echo '... uninstall uninstall the library' - -.PHONY: help version - -# -# Object rules -# - -$(VXSDK_PREFIX_BUILD)%.o: -ifeq ($(VERBOSE),true) - @ mkdir -p $(dir $@) - sh-elf-vhex-gcc \ - $(cflags) -D FXCG50 \ - -o $@ \ - -c $(addprefix src/,$(subst _,/,$(notdir $(basename $@)))) -else - @ mkdir -p $(dir $@) - @ printf "$(green)>$(nocolor) $(white)$@$(nocolor)\n" - @ sh-elf-vhex-gcc \ - $(cflags) -D FXCG50 \ - -o $@ \ - -c $(addprefix src/,$(subst _,/,$(notdir $(basename $@)))) -endif - -$(VXSDK_ASSETS_BUILD)%.o: $(VXSDK_ASSETS_SRC)/% -ifeq ($(VERBOSE),true) - @ mkdir -p $(dir $@) - sh-elf-vhex-gcc $(cflags) -D FXCG50 -o $@ -c $< -else - @ mkdir -p $(dir $@) - @ printf "$(green)>$(nocolor) $(white)$@$(nocolor)\n" - @ sh-elf-vhex-gcc $(cflags) -D FXCG50 -o $@ -c $< -endif diff --git a/assets/project/src/main.c b/assets/project/src/main.c deleted file mode 100644 index d0b7f93..0000000 --- a/assets/project/src/main.c +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include - -int main(void) -{ - dclear(C_WHITE); - dtext(1, 1, C_BLACK, "Sample fxSDK add-in."); - dupdate(); - - while (1) { __asm__("sleep"); } - - //getkey(); - return 1; -} diff --git a/assets/project/vxsdk.toml b/assets/project/vxsdk.toml deleted file mode 100644 index 22cf04b..0000000 --- a/assets/project/vxsdk.toml +++ /dev/null @@ -1,8 +0,0 @@ -[project] -name = 'vxaddin' - -[dependencies] -vxKernel = 'dev' - -[build] -build = 'make' diff --git a/install.sh b/install.sh index b747236..8cf6268 100755 --- a/install.sh +++ b/install.sh @@ -20,6 +20,7 @@ Actions: uninstall Uninstall the VxSDK Options: + --force Force reinstallation --prefix= Installation prefix (default is ~/.local) -h, --help Display this help OEF @@ -33,6 +34,7 @@ OEF # target='install' +force_reinstall='false' for arg; do case "$arg" in --help | -h) @@ -40,6 +42,9 @@ for arg; do case "$arg" in -v | --version) echo "$VERSION" exit 0;; + --force) + force_reinstall='true' + ;; install) target='install';; @@ -65,7 +70,7 @@ then if [[ -d "$prefix/lib/vxsdk/vxsdk" ]] then echo 'warning : vxsdk is already installed !' >&2 - read -n 1 -p 'Do you whant to re-install the vxSDK [y/N] ? ' reinstall + read -n 1 -p 'Do you whant to re-install the vxSDK [y/N] ? ' -r reinstall [[ "$reinstall" != 'y' ]] && exit 1 echo '' "$projdir/install.sh" uninstall-cached @@ -79,11 +84,11 @@ then "$prefix/lib/vxsdk/" install -d "$prefix/bin" - echo '#! /usr/bin/env bash' > $prefix/bin/vxsdk - echo '' >> $prefix/bin/vxsdk - echo "source $prefix/lib/vxsdk/venv/bin/activate" >> $prefix/bin/vxsdk - echo "python3 $prefix/lib/vxsdk/vxsdk \$@" >> $prefix/bin/vxsdk - echo 'deactivate' >> $prefix/bin/vxsdk + echo '#! /usr/bin/env bash' > "$prefix/bin/vxsdk" + echo '' >> "$prefix/bin/vxsdk" + echo "source $prefix/lib/vxsdk/venv/bin/activate" >> "$prefix/bin/vxsdk" + echo "python3 $prefix/lib/vxsdk/vxsdk \$@" >> "$prefix/bin/vxsdk" + echo 'deactivate' >> "$prefix/bin/vxsdk" chmod +x "$prefix/bin/vxsdk" build_date=$(date '+%Y-%m-%d') @@ -94,17 +99,17 @@ then -e "s*%BUILD_HASH%*$build_hash*" \ -e "s*%BUILD_DATE%*$build_date*" \ "$projdir/vxsdk/__main__.py" \ - > $f + > "$f" - mkdir -p $prefix/share/vxsdk + mkdir -p "$prefix/share/vxsdk" - cd $prefix/lib/vxsdk - if [[ ! -d venv ]]; + cd "$prefix/lib/vxsdk" || exit 1 + if [[ ! -d venv ]] || [[ "$force_reinstall" == 'true' ]] then set -x; python3 -m venv venv; set +x source venv/bin/activate set -x - pip install --upgrade pip 2>&1 > /dev/null + { pip install --upgrade pip > /dev/null ; } 2>&1 pip install -r requirements.txt set +x deactivate @@ -121,9 +126,9 @@ fi if [[ "$target" = 'uninstall-cached' ]] then set -x - rm $prefix/bin/vxsdk - rm -rf $prefix/lib/vxsdk/vxsdk - rmdir $prefix/share/vxsdk 2>/dev/null || exit 0 + rm "$prefix/bin/vxsdk" + rm -rf "$prefix/lib/vxsdk/vxsdk" + rmdir "$prefix/share/vxsdk" 2>/dev/null || exit 0 echo 'vxSDK has been partially removed' exit 0 fi @@ -134,9 +139,9 @@ then # TODO : rm -rf dependencies too # TODO : add confirmation input - rm $prefix/bin/vxsdk - rm -rf $prefix/lib/vxsdk - rmdir $prefix/share/vxsdk 2>/dev/null || exit 0 + rm "$prefix/bin/vxsdk" + rm -rf "$prefix/lib/vxsdk" + rmdir "$prefix/share/vxsdk" 2>/dev/null || exit 0 echo 'vxSDK has been removed' exit 0 diff --git a/vxsdk/cli/conv/__init__.py b/vxsdk/cli/conv/__init__.py deleted file mode 100644 index 36e24f5..0000000 --- a/vxsdk/cli/conv/__init__.py +++ /dev/null @@ -1,65 +0,0 @@ -""" -cli.conv - assset conversion abstraction - -This package provides conversion abstraction (image -> source code, ELF -> -addin, ...) for the Vhex project. -""" - -from core.logger import log - -from cli.conv.doctor import doctor_conv_cli -from cli.conv.assets import assets_conv_cli -from cli.conv.addin import addin_conv_cli - -__all__ = [ - '__VXSDK_MODULE_META__', - 'cli_validate', - 'cli_parse', -] - -#--- -# Public -#--- - -__VXSDK_MODULE_META__ = ( - ['conv'], - 'assets converter', - """vxsdk-conv -Project assets converter - -USAGE: - vxsdk conv(-) [OPTIONS] ... - -DESCRIPTION: - Convert vhex project assets (or binary) into various form. By default, if - no action is specified, the "asset" conversion is selected. - -ACTIONS: - asset convert asset into source file or binary file - addin convert binary into addin file for vxOS - doctor try to display assets and addin information (debug) - -See `vxsdk conv- --help` for more information on a specific action -""" -) - -def cli_validate(name): - """ validate the module name """ - return name.find('conv') == 0 - -def cli_parse(argv): - """ Build subcommand entry """ - if '--help' in argv or '-h' in argv: - log.user(__VXSDK_MODULE_META__[2]) - return 0 - if argv[0].find('conv-') != 0: - argv[0] = 'conv-asset' - action = argv[0][5:] - if action == 'doctor': - return doctor_conv_cli(argv[1:]) - if action == 'asset': - return assets_conv_cli(argv[1:]) - if action == 'addin': - return addin_conv_cli(argv[1:]) - log.error(f"unable to find action '{action}'") - return 84 diff --git a/vxsdk/cli/conv/addin.py b/vxsdk/cli/conv/addin.py deleted file mode 100644 index 5169722..0000000 --- a/vxsdk/cli/conv/addin.py +++ /dev/null @@ -1,69 +0,0 @@ -""" -cli.conv.addin - vxSDK addin conversion -""" -import sys - -#from core.conv.addin import generate_addin -from core.logger import log - -__all__ = [ - 'addin_conv_cli' -] - -#--- -# Internals -#--- - -__HELP__ = """vxsdk-converter-addin -Converte binary file into Vhex OS addin. - -USAGE: - vxsdk conv addin -b BINARY ... - -DESCRIPTION: - Convert a binary file into an application for the Vhex operating system. - -OPTIONS: - -b ELF file (no check is performed in this file) - -i 92x62 pixel image path - -o output path for the generated addin - -n internal addin name - -v internal addin version -""" - -#--- -# Public -#--- - -def addin_conv_cli(argv): - """Process CLI arguments""" - if '-h' in argv or '--help' in argv: - log.user(__HELP__) - sys.exit(0) - - action = None - info = [None, None, None, None, None] - for arg in argv: - if action == '-b': - info[0] = arg - if action == '-i': - info[1] = arg - if action == '-n': - info[2] = arg - if action == '-o': - info[3] = arg - if action == '-v': - info[4] = arg - if action: - action = None - continue - if arg in ['-b', '-i', '-n', '-o', '-v']: - action = arg - continue - - if not info[0]: - log.error('converter: need binary path !') - sys.exit(84) - - log.error('not supported addin convertion') - #return generate_addin(info[0], info[1], info[2], info[3], info[4]) diff --git a/vxsdk/cli/conv/assets.py b/vxsdk/cli/conv/assets.py deleted file mode 100644 index 3aa654b..0000000 --- a/vxsdk/cli/conv/assets.py +++ /dev/null @@ -1,75 +0,0 @@ -""" -cli.conv.assets - Vhex asset converter user interface -""" -import os - -from core.logger import log -from core.conv import assets_generate - -__all__ = [ - 'assets_conv_cli' -] - -#--- -# Internals -#--- - -__HELP__ = """vxsdk-converter-asset -Convert all assets file in the project directory. - -USAGE: - vxsdk conv-asset [project path] [OPTIONS] - -DESCRIPTION: - Convert all assets file in the asset directory. This part of the converter - module will scan the provided folder (or the current working directory) and - will try to find all `vxconv.txt` file, which describe all assets that - should be converted. - - If no argument is provided, then the current working directory is used as - asset prefix and a storag for all generated source file. You can modify - this behaviour using OPTIONS. - - For more information about the `vxconv.txt` in the wiki. - -OPTIONS: - -o The prefix for source file that will be generated - -h, --help Display this help -""" - -#--- -# Public -#--- - -def assets_conv_cli(argv): - """Process CLI arguments""" - # check obvious flags - if '-h' in argv or '--help' in argv: - log.user(__HELP__) - return 0 - - # fetch user indication - manual_output = False - prefix_output = None - prefix_asset = None - for arg in argv: - if arg == '-o': - manual_output = True - continue - if manual_output: - prefix_output = arg - continue - if prefix_asset: - log.warn(f"warning: previous path ({prefix_asset}) dropped") - prefix_asset = arg - - # check indication - if not prefix_asset: - prefix_asset = os.getcwd() - if not prefix_output: - prefix_output = os.getcwd() - prefix_asset = os.path.abspath(prefix_asset) - prefix_output = os.path.abspath(prefix_output) - - # generate asset information - return assets_generate(prefix_asset, prefix_output, True) diff --git a/vxsdk/cli/conv/doctor.py b/vxsdk/cli/conv/doctor.py deleted file mode 100644 index 19be32c..0000000 --- a/vxsdk/cli/conv/doctor.py +++ /dev/null @@ -1,24 +0,0 @@ -""" -cli.conv.doctor - vxSDK converter doctor. -""" -import sys - -from core.logger import log - -__all__ = [ - 'doctor_conv_cli' -] - -#--- -# Public -#--- - -def doctor_conv_cli(_): - """Process CLI handling - - TODO: - > give asset file description to check error - > try to display asset and addin information based on the project type - """ - log.warn('conv: doctor action not implemented yet') - sys.exit(84) diff --git a/vxsdk/cli/project.py b/vxsdk/cli/project.py deleted file mode 100644 index fb5bca7..0000000 --- a/vxsdk/cli/project.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -cli.project - handles project creation and more -""" -import sys - -from core.project import new_project -from core.logger import log - -__all__ = [ - '__VXSDK_MODULE_META__', - 'cli_validate', - 'cli_parse' -] - -#--- -# Public -#--- - -__VXSDK_MODULE_META__ = ( - ['p', 'project'], - "project abstraction", - r"""vxsdk-project -Abstract project manipulation - -USAGE: - vxsdk project [OPTIONS] - -OPTIONS: - -h, --help Print helps information - -Common used commands: - n, new Create a new project - -See `vxsdk project --help` for more information on a specific command -""" -) - -def cli_validate(name): - """ validate the module name """ - return name in __VXSDK_MODULE_META__[0] - -def cli_parse(argv): - """ Project subcommand entry """ - if len(argv) > 1: - if '-h' in argv or '--help' in argv: - log.user(__VXSDK_MODULE_META__[2]) - sys.exit(0) - if len(argv) > 3: - if argv[0] in ['n', 'new']: - for path in argv[1:]: - new_project(path) - sys.exit(0) - log.error(__VXSDK_MODULE_META__[2]) - sys.exit(84) diff --git a/vxsdk/core/build/compile.py b/vxsdk/core/build/compile.py index 71b5bea..0447005 100644 --- a/vxsdk/core/build/compile.py +++ b/vxsdk/core/build/compile.py @@ -2,8 +2,6 @@ core.build.compile - Compilation hadling using the dependency DAG graph """ -import core.conv - from core.logger import log from core.build.rules import rules_project_exec @@ -15,20 +13,6 @@ __all__ = [ # Internals #--- -def _dep_generate_assets(dep_info, _): - dep_meta = dep_info['meta'] - counter = 0 - for prefix in dep_meta.get_assets_prefix_list(): - if counter == 0: - log.user(f"[{dep_meta.name}] generate assets...") - core.conv.assets_generate( - prefix, - f"{dep_meta.build_prefix}/converter/{dep_meta.name}", - force_generate=False - ) - counter += 1 - return 0 - def _dep_build_sources(dep_info, verbose): log.user(f"[{dep_info['meta'].name}] build sources...") return rules_project_exec( @@ -58,15 +42,12 @@ def _compile_dependency(dep, verbose): > 0 on success, negative value otherwise """ dep_meta = dep['info']['meta'] - if _dep_generate_assets(dep['info'], verbose) != 0: - log.error(f"[{dep_meta.name}] error during asset generation") - return -1 if _dep_build_sources(dep['info'], verbose) != 0: log.error(f"[{dep_meta.name}] error during source build") - return -2 + return -1 if _dep_install(dep['info'], verbose) != 0: log.error(f"[{dep_meta.name}] error during installation") - return -3 + return -2 return 0 #--- diff --git a/vxsdk/core/conv/__init__.py b/vxsdk/core/conv/__init__.py deleted file mode 100644 index 259ea92..0000000 --- a/vxsdk/core/conv/__init__.py +++ /dev/null @@ -1,72 +0,0 @@ -""" -core.conv - Vhex converter module -""" - -from core.conv.assets import assets_generate - -__all__ = [ - 'generate_assets' -] - -#--- -# Public -#--- - -def generate_assets(prefix_assets, prefix_src, force_generate=True): - r"""Generate Vhex assets. - - This function abstract the asset convertion for the Vhex Operating System. - It will walk througt the `` folder and will try to find some - files named 'vxconv.txt' wich discribe assets information of a potential - project. Then it will use them to convert assets into an appropriate source - file in C without using any Vhex-specific function (so, you can use this - converter for other project). - - The vxconv.txt file is structured like basic key/value file: - - ``` - : - type: (font, bitmap) - required - path: - required - ... - - : - ... - ``` - - Each asset file description should have at least type and name information, - and each type have potentially its own requierements. - - type = bitmap: - ================================== ======================================== - Keys name and value type Description - ================================== ======================================== - profile: Select the bitmap pixel profile - | rgb4 | RGB 4 (indexed) - | rgb4a | RGBA 4 (indexed) - | rgb8 | RGB 8 (indexed) - | rgb8a | RGBA 8 (indexed) - | rgb16 | RGB 16 (5:R, 6:G, 5:B) - | rgb16a | RGBA 16 (5:R, 5:G, 5:B, 1:A) - ================================== ======================================== - - type = font: - ================================== ======================================== - Keys name and value type Description - ================================== ======================================== - grid.size: 8x9 (widthxheight) caracter size in pixel - grid.padding: space between caracter - grig.border: space around grid - proportional: caracter are cropped - line_height: caracter line alignement - charset: charset specification - ================================== ======================================== - - @args: - > path (str) - the path to find assets - > source_prefix (str) - the path to generate image source file - - @return: - > a list of string which represents all assets sources files path - """ - return assets_generate(prefix_assets, prefix_src, force_generate) diff --git a/vxsdk/core/conv/addin.py b/vxsdk/core/conv/addin.py deleted file mode 100644 index 03066c6..0000000 --- a/vxsdk/core/conv/addin.py +++ /dev/null @@ -1,67 +0,0 @@ -#from core.conv.pixel import rgba8conv -# -#from PIL import Image -#import os -# -#__all__ = [ -# 'generate_addin' -#] -# -# -#def generate_addin(binary, icon=None, name=None, output=None, version=None): -# r"""Generate an addin for the Vhex Operating System. -# -# The addin name (passed through the `name` argument) is optional here. In -# this case, the name will use the internal name...which can be guessed using -# the binary name (e.i '/path/to/the/super_addin.elf' -> internal name = -# 'super_addin' -> output name = '/path/to/the/super_addin'). -# -# The output path for the generated file is, by defautl, the same path that -# the binary but the suffix '.vxos' will be added. -# -# if the icon is not specified, a default blank icon will be used. -# -# Args: -# > binary (str) - binary path -# > icon (str) - addin icon path (optional) -# > name (str) - addin name (displayed in the menu) (optional) -# > output (str) - output path for the generated addin (optional) -# -# _fixme: -# > generate default internal name -# > change 8-bits icon into rgb565 -# > add internal addin version in the header -# """ -# if not os.path.exists(binary): -# logger(LOG_ERR, 'binary path is invalid') -# sys.exit(84) -# if icon and not os.path.exists(icon): -# logger(LOG_WARN, f'{icon}: icon does not exists, ignored') -# icon = None -# if not name: -# name = '' -# if not output: -# output = binary + '.vxos' -# -# if icon: -# bitmap = Image.open(icon) -# if bitmap.size != (92, 64): -# logger( -# LOG_ERR, -# f'{icon}:icon size does not match {bitmap.size} != (92, 64)', -# exit=84 -# ) -# -# with open(binary, 'rb') as b: -# with open(output, 'wb') as a: -# a.write(b'VHEX') -# a.write(name.encode('utf8')) -# a.write(b'\x00') -# if icon: -# for pixel in bitmap.getdata(): -# a.write(rgba8conv(pixel).to_bytes(1, 'big')) -# else: -# a.write(bytes(92*64)) -# a.write(b.read()) -# -# return 0 diff --git a/vxsdk/core/conv/assets.py b/vxsdk/core/conv/assets.py deleted file mode 100644 index e59acd3..0000000 --- a/vxsdk/core/conv/assets.py +++ /dev/null @@ -1,132 +0,0 @@ -""" -core.conv.assets - Vhex assets converter -""" -import os -import toml - -from core.logger import log -from core.conv.type.font import font_generate -from core.conv.type.image import image_generate - -__all__ = [ - 'assets_generate' -] - -#--- -# Internals -#--- - -class _VxAssetException(Exception): - """ simple exception wrapper """ - -class _VxAsset(): - """Represent a asset object - - This is an internal class which represents assets information with some - methods to abstract conversion and file type manipulation (for asset type - font and asset type bitmap). - - Also note that this class is private because we use a tricky optimization - to parse the `vxconv.txt` file, this is why we have no "private" property - with setter and getter, and why this class is "hidden". - - Some important methods to note: - - ================================== ======================================= - Name Description - ================================== ======================================= - generate() Generate the source file (C) - ================================== ======================================= - - """ - def __init__(self, prefix, name, meta): - if 'path' not in meta: - raise _VxAssetException(f"[{name}] missing path information") - if 'type' not in meta: - raise _VxAssetException(f"[{name}] missing type information") - if meta['type'] not in ['font', 'image']: - raise _VxAssetException(f"asset type '{meta[type]}' is not known") - - self._name = name - self._meta = meta - self._type = meta['type'] - self._path = prefix + '/' + meta['path'] - if not os.path.exists(self.path): - raise _VxAssetException( - "asset path '{self._path}' cannot be openned" - ) - - def __repr__(self): - return f'<_VxAssetObj, {self.name}>' - - def __str__(self): - content = f"[{self.name}]\n" - content += f" - type: {self.type}\n" - content += f" - path: {self.path}\n" - return content - - #--- - # Getter - #--- - - @property - def path(self): - """ path""" - return self._path - - @property - def name(self): - """ name""" - return self._name - - @property - def type(self): - """ type""" - return self._type - - @property - def meta(self): - """ meta""" - return self._meta - - #--- - # Public method - #--- - - def generate_source_file(self, prefix_output, force_generate): - """generate source file """ - if self.type == 'font': - return font_generate(self, prefix_output, force_generate) - return image_generate(self, prefix_output, force_generate) - -#--- -# Public -#--- - -def assets_generate(prefix_assets, prefix_output, force_generate): - """ Walk through the assets prefix and generate all source file - - @args - > prefix_asset (str) - prefix used for recursivly search for asset info - > prefix_output (str) - prefix used for the output of generated file - > force_generate (bool) - force generate the source file - - @return - > a list of all generated sources pathname - """ - if not os.path.exists(prefix_output): - os.makedirs(prefix_output) - generated = [] - for root, _, files in os.walk(prefix_assets): - if 'vxconv.toml' not in files: - continue - with open(f"{root}/vxconv.toml", 'r', encoding='utf-8') as inf: - content = toml.loads(inf.read()) - for asset_name in content: - log.user(f"converting {asset_name}...") - asset = _VxAsset(root, asset_name, content[asset_name]) - generated += asset.generate_source_file( - prefix_output, - force_generate - ) - return generated diff --git a/vxsdk/core/conv/pixel.py b/vxsdk/core/conv/pixel.py deleted file mode 100644 index cf49c55..0000000 --- a/vxsdk/core/conv/pixel.py +++ /dev/null @@ -1,45 +0,0 @@ -""" -core.conv.pixel - Pixel converter utilities -""" - -__all__ = [ - 'pixel_rgb24to16' -] - -#--- -# Public -#--- - -def pixel_rgb24to16(rgb): - """ convert RGB24 -> RGB16-565""" - _r = (rgb[0] & 0xff) >> 3 - _g = (rgb[1] & 0xff) >> 2 - _b = (rgb[2] & 0xff) >> 3 - return (_r << 11) | (_g << 5) | _b - -#def rgb1conv(pixel): -# """ Convert RGB -> 1-bit color """ -# return pixel == (0, 0, 0) - -#def rgb8conv(pixel): -# """ Convert RGB8 -> """ -# return int((pixel[0] * 7) / 255) << 5 \ -# | int((pixel[1] * 4) / 255) << 3 \ -# | int((pixel[2] * 7) / 255) << 0 - -#def rgba8conv(pixel): -# return int((pixel[0] * 4) / 256) << 6 \ -# | int((pixel[1] * 8) / 256) << 3 \ -# | int((pixel[2] * 4) / 256) << 1 \ -# | (len(pixel) >= 4 and pixel[3] == 0) - -#def rgb16conv(pixel): -# return int((pixel[0] * 31) / 255) << 11 \ -# | int((pixel[1] * 63) / 255) << 5 \ -# | int((pixel[2] * 31) / 255) << 0 - -#def rgba16conv(pixel): -# return int((pixel[0] * 31) / 255) << 11 \ -# | int((pixel[1] * 63) / 255) << 6 \ -# | int((pixel[2] * 31) / 255) << 1 \ -# | (pixel[3] != 0) diff --git a/vxsdk/core/conv/type/__init__.py b/vxsdk/core/conv/type/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/vxsdk/core/conv/type/font.py b/vxsdk/core/conv/type/font.py deleted file mode 100644 index 7d182b4..0000000 --- a/vxsdk/core/conv/type/font.py +++ /dev/null @@ -1,468 +0,0 @@ -""" -core.conv.type.font - Vhex font converter -""" -import os - -from PIL import Image - -from core.logger import log - -__all__ = [ - 'font_generate' -] - -#--- -# Internals -#--- - -## Font meta info - -def _font_fetch_info(asset): - """ Check and fetch font information - - @arg - > asset (VxAsset) - asset information - - @return - > dictionary with font information - """ - # generate font default information - font_info = { - # user can customise - 'charset' : 'normal', - 'grid_size_x' : 0, - 'grid_size_y' : 0, - 'grid_padding' : 1, - 'grid_border' : 1, - 'is_proportional' : False, - 'line_height' : 0, - 'char_spacing' : 1, - - # generated "on-the-fly" by the conversion step - # @notes - # This is mainly to provide cache for the Vhex operating system to - # speed-up render calculation by avoiding recurent caculation. - 'glyph_size' : 0, - 'glyph_height' : 0, - 'font_size' : 0, - 'data' : [] - } - - # handle user meta-indication - if 'charset' in asset.meta: - if asset.meta['charset'] not in ['default', 'unicode']: - log.error(f"Unknown charset '{asset.meta['charset']}', abord") - return None - font_info['charset'] = asset.meta['charset'] - if 'grid_size' not in asset.meta: - log.error("Missing critical grid size information, abord") - return None - grid_size = asset.meta['grid_size'].split('x') - font_info['grid_size_x'] = int(grid_size[0]) - font_info['grid_size_y'] = int(grid_size[1]) - if 'grid_padding' in asset.meta: - font_info['grid_padding'] = int(asset.meta['grid_padding']) - if 'grid_border' in asset.meta: - font_info['grid_border'] = int(asset.meta['grid_border']) - if 'proportional' in asset.meta: - font_info['is_proportional'] = asset.meta['proportional'] - font_info['line_height'] = font_info['grid_size_y'] - if 'line_height' in asset.meta: - font_info['line_height'] = asset.meta['line_height'] - if 'char_spacing' in asset.meta: - font_info['char_spacing'] = asset.meta['char_spacing'] - font_info['glyph_height'] = font_info['grid_size_y'] - - # return font information - return font_info - -## Glyph handling - -def _glyph_get_wgeometry(geometry_info, img_raw, img_size, pos, grid_size): - """ Generate glyph width geometry information - - @args - > geometry_info (dict) - geometry information - > img_raw (list) - list of all pixel of the image - > img_size (tuple) - image width and image height - > pos (tuple) - glyph position information (X and Y in pixel) - > grid_size (tuple) - glyph grid size information (width and height) - - @return - > Nothing - """ - - geometry_info['wstart'] = -1 - geometry_info['wend'] = -1 - - _px = pos[0] - _py = pos[1] - log.debug(f'[geometry] X:{pos[0]} Y:{int(pos[1]/img_size[0])}') - log.debug(f' - grid_size = {grid_size}') - for _ in range(0, grid_size[1]): - for offx in range(0, grid_size[0]): - if img_raw[_py + (_px + offx)][:3] == (255, 255, 255): - continue - if geometry_info['wstart'] < 0 or offx < geometry_info['wstart']: - geometry_info['wstart'] = offx - if geometry_info['wstart'] < 0 or offx > geometry_info['wend']: - geometry_info['wend'] = offx - _py += img_size[0] - geometry_info['wend'] += 1 - log.debug(f' - geometry = {geometry_info}') - -def _glyph_encode(data_info, img_info, geometry, posx, posy): - """ Encode glyph bitmap - - @args - > data_info (dict) - internal data information (list, index and shift) - > img_info (dict) - image-related information (object and raw content) - > geometry (dict) - geometry information - > posx (int) - X-axis position in pixel - > posy (int) - Y-axis position in pixel - - @return - > Nothing - """ - # fetch information - img = img_info['obj'] - img_raw = img_info['raw'] - data = data_info['table'] - data_idx = data_info['idx'] - data_shift = data_info['shift'] - wstart = geometry['wstart'] - wend = geometry['wend'] - - # encode the glyph - yoff = 0 - log.debug(f'[encode] X:{posx} Y:{int(posy/img.size[0])}') - for _h in range(geometry['hstart'], geometry['hend']): - for _w in range(wstart, wend): - if img_raw[(posy + yoff) + (posx + _w)][:3] == (0, 0, 0): - log.debug('#', end='') - data[data_idx] |= 0x80000000 >> data_shift - else: - log.debug('.', end='') - data[data_idx] &= ~(0x80000000 >> data_shift) - if (data_shift := data_shift + 1) >= 32: - data_shift = 0 - data_idx += 1 - log.debug('') - yoff += img.size[0] - - # commit modification - data_info['idx'] = data_idx - data_info['shift'] = data_shift - -## Font convert handling - -def _font_convert_proportional(packed_info): - """ Generate proportional font - - Proportional font means that each character have its own width size (but - have a common height). We need to performs more complexe handling than the - monospaced one. - - @args - > asset (VxAsset) - asset information - > font_information (dict) - font indication - - @return - > 0 if success, negative value otherwise - """ - # unpack information - font_info = packed_info[0] - img_info = packed_info[1] - glyph_info = packed_info[2] - data_info = packed_info[4] - geometry_info = packed_info[5] - - # isolate needed information - img = img_info['obj'] - img_raw = img_info['raw'] - nb_col = packed_info[3][0] - nb_row = packed_info[3][1] - gwidth = glyph_info[0] - gheight = glyph_info[1] - - # main loop, walk glyph per glyph - _py = (font_info['grid_border'] + font_info['grid_padding']) * img.size[0] - for _ in range(0, nb_row): - _px = font_info['grid_border'] + font_info['grid_padding'] - for _ in range(0, nb_col): - # generate width geometry information - _glyph_get_wgeometry( - geometry_info, - img_raw, - img.size, - (_px, _py), - (font_info['grid_size_x'], font_info['grid_size_y']) - ) - - # save critical glyph geometry information that will be encoded in - # the final C source file - font_info['glyph_props'].append(( - geometry_info['wend'] - geometry_info['wstart'], - data_info['idx'], - data_info['shift'] - )) - - # encode glyph information - _glyph_encode(data_info, img_info, geometry_info, _px, _py) - - # update loop information - font_info['glyph_count'] += 1 - _px += gwidth - _py += gheight * img.size[0] - return 0 - -def _font_convert_monospaced(packed_info): - """ Generate proportional font - - Proportional font means that each character have its own width size (but - have a common height). We need to performs more complexe handling than the - monospaced one. - - @args - > asset (VxAsset) - asset information - > font_information (dict) - font indication - - @return - > 0 if success, negative value otherwise - """ - # unpack information - font_info = packed_info[0] - img_info = packed_info[1] - glyph_info = packed_info[2] - grid_info = packed_info[3] - data_info = packed_info[4] - geometry_info = packed_info[5] - - # isolate needed information - img = img_info['obj'] - nb_row = grid_info[1] - nb_col = grid_info[0] - gwidth = glyph_info[0] - gheight = glyph_info[1] - - # main loop, walk glyph per glyph - _py = (font_info['grid_border'] + font_info['grid_padding']) * img.size[0] - for _ in range(0, nb_row): - _px = font_info['grid_border'] + font_info['grid_padding'] - for _ in range(0, nb_col): - _glyph_encode(data_info, img_info, geometry_info, _px, _py) - font_info['glyph_count'] += 1 - _px += gwidth - _py += gheight * img.size[0] - return 0 - -def _font_convert(asset, font_info): - """ Generate font information - - @args - > asset (VxAsset) - asset information - > font_info (dict) - font information - - @return - > 0 if success, negative value otherwise - """ - # generate image information - img = Image.open(asset.path) - img_raw = img.getdata() - img_info = { - 'obj' : img, - 'raw' : img_raw - } - - # pre-calculate the "real" glyph width and height using padding information - glyph_info = [0, 0] - glyph_info[0] = font_info['grid_size_x'] + font_info['grid_padding'] - glyph_info[1] = font_info['grid_size_y'] + font_info['grid_padding'] - gheight = glyph_info[1] - gwidth = glyph_info[0] - log.debug(f"gwidth = {gwidth} && gheight = {gheight}") - - # pre-calculate the number of row and column of the font - grid_info = [0, 0] - grid_info[0] = int((img.size[0] - (font_info['grid_border'] * 2)) / gwidth) - grid_info[1] = int((img.size[1] - (font_info['grid_border'] * 2)) /gheight) - nb_col = grid_info[0] - nb_row = grid_info[1] - log.debug(f"nb_row = {nb_row} && nb_col = {nb_col}") - - # pre-calculate and prepare per-glyph information - # @note - # The generated data is designed for 4-alignement padding. This to have - # speed-up on drawing function. - font_info['glyph_size'] = font_info['grid_size_x'] - font_info['glyph_size'] *= font_info['grid_size_y'] - font_info['font_size'] = font_info['glyph_size'] * nb_row * nb_col - font_info['glyph_count'] = 0 - font_info['glyph_props'] = [] - font_info['data'] = [0] * int((font_info['font_size'] + 31) / 32) - log.debug(f"data original = {id(font_info['data'])}") - - # generate data information - data_info = { - 'table' : font_info['data'], - 'idx' : 0, - 'shift' : 0 - } - log.debug(f"data packed = {id(data_info['table'])}") - - # generate geometry information - geometry_info = { - 'hstart' : 0, - 'hend' : font_info['grid_size_y'], - 'wstart' : 0, - 'wend' : font_info['grid_size_x'], - } - - # select the converter - converter = _font_convert_monospaced - if font_info['is_proportional']: - converter = _font_convert_proportional - - # convert font - converter(( - font_info, - img_info, - glyph_info, - grid_info, - data_info, - geometry_info - )) - - log.debug(f"data packed end = {id(data_info['table'])}") - return 0 - -## Font generator - -def _font_generate_unicode_source(_): - """ Unicode special chaset directory """ - log.error("unicode conversion not implemented yet o(x_x)o") - return '' - -def _font_generate_normal_source(font_info): - """ Print chaset is a image file - """ - content = "\t.glyph = {\n" - content += f"\t\t.height = {font_info['glyph_height']},\n" - content += f"\t\t.line_height = {font_info['line_height']},\n" - - # encode font bitmap - line = 0 - log.debug(f"data = {font_info['data']}") - content += "\t\t.data = (uint32_t[]){\n" - for pixel in font_info['data']: - if line == 0: - content += '\t\t\t' - if line >= 1: - content += ' ' - content += f"{pixel:#010x}," - if (line := line + 1) == 4: - content += '\n' - line = 0 - if line != 0: - content += '\n' - content += '\t\t},\n' - - # indicate the number of glyph in the bitmap - content += f"\t\t.count = {font_info['glyph_count']},\n" - - # encode proportional information if needed - if font_info['is_proportional']: - content += '\t\t.prop = (struct __workaround[]){\n' - for prop in font_info['glyph_props']: - content += "\t\t\t{\n" - content += f"\t\t\t\t.width = {prop[0]},\n" - content += f"\t\t\t\t.index = {prop[1]},\n" - content += f"\t\t\t\t.shift = {prop[2]},\n" - content += "\t\t\t},\n" - else: - content += "\t\t.mono = {,\n" - content += f"\t\t\t.width = {font_info['glyph_width']},\n" - content += f"\t\t\t.size = {font_info['glyph_size']},\n" - content += "\t\t},\n" - content += "\t},\n" - - # skip unicode struct - content += "\t.unicode = {\n" - content += "\t\t.blocks = NULL,\n" - content += "\t\t.block_count = 0,\n" - content += "\t}\n" - return content - -def _font_generate_source_file(asset, font_info): - """ Generate font source file content - - @args - > asset (VxAsset) - asset information - > info (dict) - hold font information - - @return - > file C content string - """ - # generate basic header - content = "#include \n" - content += "\n" - content += f"/* {asset.name} - Vhex asset\n" - content += " This object has been converted by using the vxSDK " - content += "converter */\n" - content += f"struct font const {asset.name} = " + "{\n" - content += f"\t.name = \"{asset.name}\",\n" - - # shape information - content += "\t.shape = {\n" - content += "\t\t.bold = 0,\n" - content += "\t\t.italic = 0,\n" - content += "\t\t.serif = 0,\n" - content += "\t\t.mono = 0,\n" - content += f"\t\t.prop = {int(font_info['is_proportional'])},\n" - content += "\t},\n" - - # manage display indication - content += f"\t.char_spacing = {font_info['char_spacing']},\n" - - # handle special charset behaviour - if font_info['charset'] == 'unicode': - content += _font_generate_unicode_source(font_info) - else: - content += _font_generate_normal_source(font_info) - - # closure and return - content += '};\n' - return content - -#--- -# Public -#--- - -def font_generate(asset, prefix_output, force_generate): - """ Convert an image asset to a C source file - - @args - > asset (_VxAsset) - minimal asset information - > prefix_output (str) - prefix for source file generation - > force_generate (bool) - force generate the source file - - @return - > pathname of the generated file - """ - # check if the asset already exists - asset_src = f'{prefix_output}/{asset.name}_vxfont.c' - if not force_generate and os.path.exists(asset_src): - return asset_src - - # generate font information - if not (font_info := _font_fetch_info(asset)): - return '' - if _font_convert(asset, font_info) != 0: - return '' - content = _font_generate_source_file(asset, font_info) - - # create the source file - with open(asset_src, "w", encoding='utf8') as file: - file.write(content) - log.debug(f"source file generated at {asset_src}") - return asset_src diff --git a/vxsdk/core/conv/type/image.py b/vxsdk/core/conv/type/image.py deleted file mode 100644 index e166efe..0000000 --- a/vxsdk/core/conv/type/image.py +++ /dev/null @@ -1,403 +0,0 @@ -""" -core.conv.type.image - Vhex image converter -""" -import os - -from PIL import Image - -from core.logger import log -from core.conv.pixel import pixel_rgb24to16 - -__all__ = [ - 'image_generate' -] - -#--- -# Internals -#--- - -## Profile handling - -def _profile_gen(profile, name, palette=None, alpha=None): - r""" Internal image profile class - - ================================== ======================================== - Property Description - ================================== ======================================== - id (int) profile ID - names (array of str) list all profile names - format (str) profile format name (vhex API) - has_alpha (bool) indicate if the profil has alpha - alpha (int) alpha index in the palette (or mask) - is_indexed (bool) indicate if it should be indexed - palette_base (int) indicate base index for color inserting - palette_color_count (int) indicate the number of color (palette) - palette_trim (bool) indicate if the palette should be trimed - ================================== ======================================== - """ - profile = { - 'profile' : profile, - 'name' : name, - 'has_alpha' : (alpha is not None), - 'alpha' : alpha, - 'is_indexed': (palette is not None), - 'palette' : None - } - if palette is not None: - profile['palette_base'] = palette[0] - profile['palette_color_count'] = palette[1] - profile['palette_trim'] = palette[2] - return profile - -# all supported profile information -VX_PROFILES = [ - _profile_gen('IMAGE_RGB565', "p16"), - _profile_gen('IMAGE_RGB565A', "p16a", alpha=0x0001), - _profile_gen('IMAGE_P8_RGB565', "p8", palette=(0,256,True)), - _profile_gen('IMAGE_P8_RGB565A', "p8a", palette=(1,256,True), alpha=0), - _profile_gen('IMAGE_P4_RGB565', "p4", palette=(0,16,False)), - _profile_gen('IMAGE_P4_RGB565A', "p4a", palette=(1,16,False), alpha=0), -] - -def _profile_find(name): - """Find a profile by name.""" - for profile in VX_PROFILES: - if name == profile['name']: - return profile - return None - -## Image manipulation - -def _image_isolate_alpha(info): - """ Isolate alpha corlor of the image - - Vhex use a particular handling for alpha color and this information should - use a strict encoding way. Things that Pillow don't do properly. So, lets - manually setup our alpha isolation and patch Pillow alpha palette handling. - - @args - > info (dict) - contains all needed information (image, data, ...) - - @return - > Nothing - """ - # fetch needed information - img = info['img'] - profile = info['profile'] - - # Save the alpha channel and make it 1-bit. We need to do this because - # the alpha value is handled specialy in Vhex and the image conversion - # to palette-oriented image is weird : the alpha colors is also converted - # in the palette - if profile['has_alpha']: - alpha_channel = img.getchannel("A").convert("1", dither=Image.NONE) - else: - alpha_channel = Image.new("1", img.size, 1) - - alpha_pixels = alpha_channel.load() - img = img.convert("RGB") - - # Transparent pixels have random values on the RGB channels, causing - # them to use up palette entries during quantization. To avoid that, set - # their RGB data to a color used somewhere else in the image. - pixels = img.load() - bg_color = next( - ( - pixels[x,y] - for x in range(img.width) - for y in range(img.height) - if alpha_pixels[x,y] > 0 - ), - (0,0,0) - ) - for _y in range(img.height): - for _x in range(img.width): - if alpha_pixels[_x, _y] == 0: - pixels[_x, _y] = bg_color - - # update external information - info['img'] = img - info['img_pixel_list_alpha'] = alpha_pixels - info['img_pixel_list_clean'] = pixels - -def _image_encode_palette(info): - """ Generate palette information - - This routine is involved only if the targeted profile is indexed. We need - to generate (and isolate) color palette. - - @args - > info (dict) - contains all needed information (image, data, ...) - - @return - > Nothing - """ - # fetch needed information - img = info['img'] - profile = info['profile'] - - # convert image into palette format - # note: we remove one color slot in the palette for the alpha one - color_count = profile['palette_color_count'] - int(profile['has_alpha']) - img = img.convert( - 'P', - dither=Image.NONE, - palette=Image.ADAPTIVE, - colors=color_count - ) - - # The palette format is a list of N triplets ([r, g, b, ...]). But, - # sometimes, colors after img.convert() are not numbered 0 to - # `color_count`, because the palette don't need to be that big. So, - # we calculate the "palette size" by walking throuth the bitmap and - # by saving the biggest index used. - pixels = img.load() - nb_triplet = 1 + max( - pixels[x,y] - for y in range(img.height) - for x in range(img.width) - ) - palette = img.getpalette()[:3 * nb_triplet] - palette = list(zip(palette[::3], palette[1::3], palette[2::3])) - - # For formats with transparency, add an "unused" palette slot which - # will used has pink/purple in case of a bad application try to use - # this value anyway - if profile['has_alpha']: - palette = [(255, 0, 255)] + palette - nb_triplet += 1 - - # Also keep track of how to remap indices from the values generated - # by img.convert() into the palette, which is shifted by 1 due to - # alpha and also starts at profile.palette_base. - # - # Note: profile.palette_base already starts 1 value later for - # formats with alpha. - palette_map = [ - (profile['palette_base'] + i) % profile['palette_color_count'] - for i in range(nb_triplet) - ] - - # Encode the palette - palette_color_count = nb_triplet - if not profile['palette_trim']: - palette_color_count = profile['palette_color_count'] - - palette_data = [0] * palette_color_count - for i, rgb24 in enumerate(palette): - palette_data[i] = pixel_rgb24to16(rgb24) - - # update internal information - info['palette_map'] = palette_map - info['palette_data'] = palette_data - info['palette_color_count'] = palette_color_count - info['nb_triplet'] = nb_triplet - info['img_pixel_list_clean'] = pixels - -def _image_encode_bitmap(info): - """ Encode the bitmap - - This routine will generate the main data list which will contains the - bitmap using Vhex-specific encoding. - - @args - > info (dict) - contains all needed information (image, data, ...) - - @return - > Nothing - """ - # fetch needed information - img = info['img'] - profile = info['profile'] - alpha_pixels = info['img_pixel_list_alpha'] - pixels = info['img_pixel_list_clean'] - palette_map = info['palette_map'] - - # generate profile-specific geometry information - if profile['name'] in ['p16', 'p16a']: - # Preserve alignment between rows by padding to 4 bytes - nb_stride = ((img.width + 1) // 2) * 4 - data_size = (nb_stride * img.height) * 2 - elif profile['name'] in ['p8', 'p8a']: - nb_stride = img.width - data_size = img.width * img.height - else: - # Pad whole bytes - nb_stride = (img.width + 1) // 2 - data_size = nb_stride * img.height - - # Generate the real data map - data = [0] * data_size - - # encode the bitmap - for _y in range(img.height): - for _x in range(img.width): - # get alpha information about this pixel - _a = alpha_pixels[_x, _y] - - if profile['name'] in ['p16', 'p16a']: - # If c lands on the alpha value, flip its lowest bit to avoid - # ambiguity with alpha - _c = profile['alpha'] - if not _a: - _c = pixel_rgb24to16(pixels[_x, _y]) & ~1 - data[(img.width * _y) + _x] = _c - - elif profile['name'] in ['p8', 'p8a']: - _c = palette_map[pixels[_x,_y]] if _a > 0 else profile['alpha'] - data[(img.width * _y) + _x] = _c - - else: - _c = palette_map[pixels[_x,_y]] if _a > 0 else profile['alpha'] - offset = (nb_stride * _y) + (_x // 2) - if _x % 2 == 0: - data[offset] |= (_c << 4) - else: - data[offset] |= _c - - # update external information - info['data'] = data - info['data_size'] = data_size - info['nb_stride'] = nb_stride - info['data_size'] = data_size - -def _image_convert(asset, profile_name): - """ Image asset convertion - - @args - > asset (_VxAsset) - asset information - > profile_name (str) - profile name information - - @return - > a dictionary with all image information - """ - # generate critical information and check posible error - img_info = { - 'img' : Image.open(asset.path), - 'profile' : _profile_find(profile_name) - } - if not img_info['img']: - log.error(f"unable to open the asset '{asset.path}', abord") - return None - if not img_info['profile']: - log.error(f"unable to find the color profile '{profile_name}', abord") - return None - - # convert the bitmap and generate critical information - _image_isolate_alpha(img_info) - if img_info['profile']['is_indexed']: - _image_encode_palette(img_info) - _image_encode_bitmap(img_info) - - # return generated information - return img_info - -## source file content generation - -def _display_array(array, prefix='\t\t'): - """ Display array information (only for p16* profile) """ - line = 0 - content = '' - for pixels in array: - if line == 0: - content += prefix - if line >= 1: - content += ' ' - content += f'{pixels:#06x},' - if (line := line + 1) >= 8: - content += '\n' - line = 0 - if line != 0: - content += '\n' - return content - -def _image_generate_source_file(asset, info): - """Generate image source file - - @args - > asset (VxAsset) - asset information - > info (dict) - hold image information - - @return - > file C content string - """ - img = info['img'] - profile = info['profile'] - - # generate basic header - content = "#include \n" - content += "\n" - content += f"/* {asset.name} - Vhex asset\n" - content += " This object has been converted by using the vxSDK " - content += "converter */\n" - content += "const image_t " + f"{asset.name} = " + "{\n" - content += f"\t.format = {profile['profile']},\n" - content += "\t.flags = IMAGE_FLAGS_RO | IMAGE_FLAGS_OWN,\n" - content += f"\t.color_count = {profile['palette_color_count']},\n" - content += f"\t.width = {img.width},\n" - content += f"\t.height = {img.height},\n" - content += f"\t.stride = {info['nb_stride']},\n" - - # encode bitmap table - encode = 16 if profile['profile'] in ['p16', 'p16a'] else 8 - content += f"\t.data = (void*)(const uint{encode}_t [])" + "{\n" - for _y in range(img.height): - content += '\t\t' - for _x in range(info['nb_stride']): - pixel = info['data'][(_y * info['nb_stride']) + _x] - if profile['profile'] in ['p16', 'p16a']: - content += f'{pixel:#06x},' - elif profile['profile'] in ['p8', 'p8a']: - content += f'{pixel:#04x},' - else: - content += f'{pixel:3},' - content += '\n' - - content += '\t},\n' - - # add palette information - if 'palette_data' in info: - content += "\t.palette = (void*)(const uint16_t []){\n" - content += _display_array(info['palette_data']) - content += "\t},\n" - else: - content += "\t.palette = NULL,\n" - - # closure and return - content += '};' - return content - -#--- -# Public -#--- - -def image_generate(asset, prefix_output, force_generate): - """ Convert an image asset to a C source file - - @args - > asset (_VxAsset) - minimal asset information - > prefix_output (str) - prefix for source file generation - > force_generate (bool) - force generate the source file - - @return - > pathname of the generated file - """ - # check critical requirement - if 'profile' not in asset.meta: - log.error(f"[{asset.name}] missing profile information!") - return '' - - # check if the file already exists - asset_src = f'{prefix_output}/{asset.name}_vximage.c' - if not force_generate and os.path.exists(asset_src): - return asset_src - - #generate the source file content - if not (img_info := _image_convert(asset, asset.meta['profile'])): - return '' - content = _image_generate_source_file(asset, img_info) - - # generate the source file - with open(asset_src, "w", encoding='utf8') as file: - file.write(content) - return asset_src diff --git a/vxsdk/core/project/__init__.py b/vxsdk/core/project/__init__.py deleted file mode 100644 index 0ddb73c..0000000 --- a/vxsdk/core/project/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -""" -core.project - project abstraction -""" - -from core.project.new import new_project - -__all__ = [ - 'new' -] - -#--- -# Public -#--- - -def new(projpath): - """ create a new project from default template """ - return new_project(projpath) diff --git a/vxsdk/core/project/new.py b/vxsdk/core/project/new.py deleted file mode 100644 index 88b5c66..0000000 --- a/vxsdk/core/project/new.py +++ /dev/null @@ -1,29 +0,0 @@ -""" -core.project.new - create a new project from default template -""" -import os -import shutil - -from core.logger import log - -__all__ = [ - 'new_project' -] - -#--- -# Public -#--- - -# (todo/CDE6) : change internal project name -def new_project(project_path): - """ create a new project """ - if os.path.exists(project_path): - log.warn(f"The path {project_path} already exists !") - return True - origin_path = os.path.dirname(__file__) - shutil.copytree( - origin_path + '/../../assets/project/', - project_path - ) - log.user(f"project '{project_path}' successfully created !") - return False