Cleanup: remove unused icon utilities and make convenience target
Remove utilities to assist in creation of the now removed `*.dat` icons. Pull Request: https://projects.blender.org/blender/blender/pulls/123837
This commit is contained in:
parent
9584f8fb55
commit
a8fae77f10
14
GNUmakefile
14
GNUmakefile
@ -96,15 +96,6 @@ Spell Checkers
|
||||
Utilities
|
||||
Not associated with building Blender.
|
||||
|
||||
* icons:
|
||||
Updates PNG icons from SVG files.
|
||||
|
||||
Optionally pass in variables: 'BLENDER_BIN', 'INKSCAPE_BIN'
|
||||
otherwise default paths are used.
|
||||
|
||||
Example
|
||||
make icons INKSCAPE_BIN=/path/to/inkscape
|
||||
|
||||
* icons_geom:
|
||||
Updates Geometry icons from BLEND file.
|
||||
|
||||
@ -565,11 +556,6 @@ source_archive_complete: .FORCE
|
||||
# This assumes CMake is still using a default `PACKAGE_DIR` variable:
|
||||
@$(PYTHON) ./build_files/utils/make_source_archive.py --include-packages "$(BUILD_DIR)/source_archive/packages"
|
||||
|
||||
icons: .FORCE
|
||||
@BLENDER_BIN=$(BLENDER_BIN) "$(BLENDER_DIR)/release/datafiles/blender_icons_update.py"
|
||||
"$(BLENDER_DIR)/release/datafiles/prvicons_update.py"
|
||||
"$(BLENDER_DIR)/release/datafiles/alert_icons_update.py"
|
||||
|
||||
icons_geom: .FORCE
|
||||
@BLENDER_BIN=$(BLENDER_BIN) \
|
||||
"$(BLENDER_DIR)/release/datafiles/blender_icons_geom_update.py"
|
||||
|
@ -1040,91 +1040,6 @@ function(data_to_c_simple
|
||||
set_source_files_properties(${_file_to} PROPERTIES GENERATED TRUE)
|
||||
endfunction()
|
||||
|
||||
# Function for converting pixmap directory to a '.png' and then a '.c' file.
|
||||
function(data_to_c_simple_icons
|
||||
path_from icon_prefix icon_names
|
||||
list_to_add
|
||||
)
|
||||
|
||||
# Conversion steps
|
||||
# path_from -> _file_from -> _file_to
|
||||
# foo/*.dat -> foo.png -> foo.png.c
|
||||
|
||||
get_filename_component(_path_from_abs ${path_from} ABSOLUTE)
|
||||
# remove ../'s
|
||||
get_filename_component(_file_from ${CMAKE_CURRENT_BINARY_DIR}/${path_from}.png REALPATH)
|
||||
get_filename_component(_file_to ${CMAKE_CURRENT_BINARY_DIR}/${path_from}.png.c REALPATH)
|
||||
|
||||
list(APPEND ${list_to_add} ${_file_to})
|
||||
set(${list_to_add} ${${list_to_add}} PARENT_SCOPE)
|
||||
|
||||
get_filename_component(_file_to_path ${_file_to} PATH)
|
||||
|
||||
# Construct a list of absolute paths from input
|
||||
set(_icon_files)
|
||||
foreach(_var ${icon_names})
|
||||
list(APPEND _icon_files "${_path_from_abs}/${icon_prefix}${_var}.dat")
|
||||
endforeach()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${_file_from} ${_file_to}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory ${_file_to_path}
|
||||
# COMMAND python3 ${CMAKE_SOURCE_DIR}/source/blender/datatoc/datatoc_icon.py
|
||||
# ${_path_from_abs} ${_file_from}
|
||||
COMMAND "$<TARGET_FILE:datatoc_icon>" ${_path_from_abs} ${_file_from}
|
||||
COMMAND "$<TARGET_FILE:datatoc>" ${_file_from} ${_file_to}
|
||||
DEPENDS
|
||||
${_icon_files}
|
||||
datatoc_icon
|
||||
datatoc
|
||||
# could be an arg but for now we only create icons depending on UI_icons.hh
|
||||
${CMAKE_SOURCE_DIR}/source/blender/editors/include/UI_icons.hh
|
||||
)
|
||||
|
||||
set_source_files_properties(${_file_from} ${_file_to} PROPERTIES GENERATED TRUE)
|
||||
endfunction()
|
||||
|
||||
# XXX Not used for now...
|
||||
function(svg_to_png
|
||||
file_from
|
||||
file_to
|
||||
dpi
|
||||
list_to_add
|
||||
)
|
||||
|
||||
# remove ../'s
|
||||
get_filename_component(_file_from ${CMAKE_CURRENT_SOURCE_DIR}/${file_from} REALPATH)
|
||||
get_filename_component(_file_to ${CMAKE_CURRENT_SOURCE_DIR}/${file_to} REALPATH)
|
||||
|
||||
list(APPEND ${list_to_add} ${_file_to})
|
||||
set(${list_to_add} ${${list_to_add}} PARENT_SCOPE)
|
||||
|
||||
find_program(INKSCAPE_EXE inkscape)
|
||||
mark_as_advanced(INKSCAPE_EXE)
|
||||
|
||||
if(INKSCAPE_EXE)
|
||||
if(APPLE)
|
||||
# in OS X app bundle, the binary is a shim that doesn't take any
|
||||
# command line arguments, replace it with the actual binary
|
||||
string(REPLACE "MacOS/Inkscape" "Resources/bin/inkscape" INKSCAPE_REAL_EXE ${INKSCAPE_EXE})
|
||||
if(EXISTS "${INKSCAPE_REAL_EXE}")
|
||||
set(INKSCAPE_EXE ${INKSCAPE_REAL_EXE})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${_file_to}
|
||||
|
||||
COMMAND ${INKSCAPE_EXE}
|
||||
${_file_from} --export-dpi=${dpi} --without-gui --export-png=${_file_to}
|
||||
|
||||
DEPENDS ${_file_from} ${INKSCAPE_EXE}
|
||||
)
|
||||
else()
|
||||
message(WARNING "Inkscape not found, could not re-generate ${_file_to} from ${_file_from}!")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(msgfmt_simple
|
||||
file_from
|
||||
list_to_add
|
||||
|
@ -1,32 +0,0 @@
|
||||
if NOT EXIST %PYTHON% (
|
||||
echo python not found, required for this operation
|
||||
exit /b 1
|
||||
)
|
||||
|
||||
call "%~dp0\find_inkscape.cmd"
|
||||
|
||||
if EXIST "%INKSCAPE_BIN%" (
|
||||
goto detect_inkscape_done
|
||||
)
|
||||
|
||||
echo unable to locate inkscape, run "set inkscape_BIN=full_path_to_inkscape.exe"
|
||||
exit /b 1
|
||||
|
||||
:detect_inkscape_done
|
||||
|
||||
call "%~dp0\find_blender.cmd"
|
||||
|
||||
if EXIST "%BLENDER_BIN%" (
|
||||
goto detect_blender_done
|
||||
)
|
||||
|
||||
echo unable to locate blender, run "set BLENDER_BIN=full_path_to_blender.exe"
|
||||
exit /b 1
|
||||
|
||||
:detect_blender_done
|
||||
|
||||
%PYTHON% -B %BLENDER_DIR%\release\datafiles\blender_icons_update.py
|
||||
%PYTHON% -B %BLENDER_DIR%\release\datafiles\prvicons_update.py
|
||||
%PYTHON% -B %BLENDER_DIR%\release\datafiles\alert_icons_update.py
|
||||
|
||||
:EOF
|
@ -103,9 +103,6 @@ if NOT "%1" == "" (
|
||||
set FORMAT=1
|
||||
set FORMAT_ARGS=%2 %3 %4 %5 %6 %7 %8 %9
|
||||
goto EOF
|
||||
) else if "%1" == "icons" (
|
||||
set ICONS=1
|
||||
goto EOF
|
||||
) else if "%1" == "icons_geom" (
|
||||
set ICONS_GEOM=1
|
||||
goto EOF
|
||||
|
5
make.bat
5
make.bat
@ -78,11 +78,6 @@ call "%BLENDER_DIR%\build_files\windows\set_build_dir.cmd"
|
||||
|
||||
:convenience_targets
|
||||
|
||||
if "%ICONS%" == "1" (
|
||||
call "%BLENDER_DIR%\build_files\windows\icons.cmd"
|
||||
goto EOF
|
||||
)
|
||||
|
||||
if "%ICONS_GEOM%" == "1" (
|
||||
call "%BLENDER_DIR%\build_files\windows\icons_geom.cmd"
|
||||
goto EOF
|
||||
|
@ -1,106 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-FileCopyrightText: 2014-2022 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# This script updates icons from the SVG file
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
from typing import (
|
||||
Dict,
|
||||
List,
|
||||
Optional,
|
||||
Sequence,
|
||||
Tuple,
|
||||
)
|
||||
|
||||
|
||||
def run(cmd: Sequence[str], *, env: Optional[Dict[str, str]] = None) -> None:
|
||||
print(" ", " ".join(cmd))
|
||||
subprocess.check_call(cmd, env=env)
|
||||
|
||||
|
||||
BASEDIR = os.path.abspath(os.path.dirname(__file__))
|
||||
|
||||
env = {}
|
||||
# Developers may have ASAN enabled, avoid non-zero exit codes.
|
||||
env["ASAN_OPTIONS"] = "exitcode=0:" + os.environ.get("ASAN_OPTIONS", "")
|
||||
|
||||
# These NEED to be set on windows for python to initialize properly.
|
||||
if sys.platform[:3] == "win":
|
||||
env["PATHEXT"] = os.environ.get("PATHEXT", "")
|
||||
env["SystemDrive"] = os.environ.get("SystemDrive", "")
|
||||
env["SystemRoot"] = os.environ.get("SystemRoot", "")
|
||||
|
||||
if not (inkscape_bin := os.environ.get("INKSCAPE_BIN")):
|
||||
if sys.platform == 'darwin':
|
||||
inkscape_bin = '/Applications/Inkscape.app/Contents/MacOS/inkscape'
|
||||
else:
|
||||
inkscape_bin = "inkscape"
|
||||
|
||||
blender_bin = os.environ.get("BLENDER_BIN", "blender")
|
||||
|
||||
cmd: Tuple[str, ...] = (
|
||||
inkscape_bin,
|
||||
os.path.join(BASEDIR, "blender_icons.svg"),
|
||||
"--export-width=602",
|
||||
"--export-height=640",
|
||||
"--export-type=png",
|
||||
"--export-filename=" + os.path.join(BASEDIR, "blender_icons16.png"),
|
||||
)
|
||||
run(cmd, env=env)
|
||||
|
||||
cmd = (
|
||||
inkscape_bin,
|
||||
os.path.join(BASEDIR, "blender_icons.svg"),
|
||||
"--export-width=1204",
|
||||
"--export-height=1280",
|
||||
"--export-type=png",
|
||||
"--export-filename=" + os.path.join(BASEDIR, "blender_icons32.png"),
|
||||
)
|
||||
run(cmd, env=env)
|
||||
|
||||
|
||||
# For testing it can be good to clear all old
|
||||
# rm ./blender_icons16/*.dat
|
||||
# rm ./blender_icons32/*.dat
|
||||
|
||||
datatoc_icon_split_py = os.path.join(BASEDIR, "..", "..", "source", "blender", "datatoc", "datatoc_icon_split.py")
|
||||
|
||||
# create .dat pixmaps (which are stored in git)
|
||||
cmd = (
|
||||
blender_bin, "--background", "--factory-startup",
|
||||
"--python", datatoc_icon_split_py, "--",
|
||||
"--image=" + os.path.join(BASEDIR, "blender_icons16.png"),
|
||||
"--output=" + os.path.join(BASEDIR, "blender_icons16"),
|
||||
"--output_prefix=icon16_",
|
||||
"--name_style=UI_ICONS",
|
||||
"--parts_x", "26", "--parts_y", "30",
|
||||
"--minx", "3", "--maxx", "53", "--miny", "3", "--maxy", "8",
|
||||
"--minx_icon", "2", "--maxx_icon", "2", "--miny_icon", "2", "--maxy_icon", "2",
|
||||
"--spacex_icon", "1", "--spacey_icon", "1",
|
||||
)
|
||||
run(cmd, env=env)
|
||||
|
||||
cmd = (
|
||||
blender_bin, "--background", "--factory-startup",
|
||||
"--python", datatoc_icon_split_py, "--",
|
||||
"--image=" + os.path.join(BASEDIR, "blender_icons32.png"),
|
||||
"--output=" + os.path.join(BASEDIR, "blender_icons32"),
|
||||
"--output_prefix=icon32_",
|
||||
"--name_style=UI_ICONS",
|
||||
"--parts_x", "26", "--parts_y", "30",
|
||||
"--minx", "6", "--maxx", "106", "--miny", "6", "--maxy", "16",
|
||||
"--minx_icon", "4", "--maxx_icon", "4", "--miny_icon", "4", "--maxy_icon", "4",
|
||||
"--spacex_icon", "2", "--spacey_icon", "2",
|
||||
)
|
||||
run(cmd, env=env)
|
||||
|
||||
os.remove(os.path.join(BASEDIR, "blender_icons16.png"))
|
||||
os.remove(os.path.join(BASEDIR, "blender_icons32.png"))
|
||||
|
||||
# For testing, if we want the PNG of each image
|
||||
# ./datatoc_icon_split_to_png.py ./blender_icons16/*.dat
|
||||
# ./datatoc_icon_split_to_png.py ./blender_icons32/*.dat
|
@ -11,42 +11,3 @@ set(SRC
|
||||
|
||||
# SRC_DNA_INC is defined in the parent dir
|
||||
add_executable(datatoc ${SRC})
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Build datatoc_icon executable
|
||||
|
||||
if(NOT WITH_HEADLESS)
|
||||
|
||||
set(SRC
|
||||
datatoc_icon.cc
|
||||
)
|
||||
setup_platform_linker_flags(datatoc)
|
||||
if(WIN32)
|
||||
include_directories(
|
||||
../blenlib
|
||||
../../../intern/utfconv
|
||||
)
|
||||
|
||||
# for winstuff_dir.cc
|
||||
add_definitions(-DUSE_STANDALONE)
|
||||
|
||||
list(APPEND SRC
|
||||
../blenlib/intern/winstuff_dir.cc
|
||||
../../../intern/utfconv/utfconv.cc
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
include_directories(${PNG_INCLUDE_DIRS})
|
||||
|
||||
add_executable(datatoc_icon ${SRC})
|
||||
setup_platform_linker_flags(datatoc_icon)
|
||||
|
||||
target_link_libraries(datatoc_icon ${PNG_LIBRARIES} ${ZLIB_LIBRARIES})
|
||||
# PNG library uses pow() and floow(), so seems -lm is required for proper
|
||||
# working binary.
|
||||
if(UNIX AND NOT APPLE)
|
||||
target_link_libraries(datatoc_icon m)
|
||||
endif()
|
||||
endif()
|
||||
|
@ -1,496 +0,0 @@
|
||||
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup datatoc
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <cerrno>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
/* for bool */
|
||||
#include "../blenlib/BLI_sys_types.h"
|
||||
|
||||
/* for DIR */
|
||||
#if !defined(WIN32) || defined(FREEWINDOWS)
|
||||
# include <dirent.h>
|
||||
#endif
|
||||
|
||||
#include <png.h>
|
||||
|
||||
/* for Win32 DIR functions */
|
||||
#ifdef WIN32
|
||||
# include "../blenlib/BLI_winstuff.h"
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
# define SEP '\\'
|
||||
#else
|
||||
# define SEP '/'
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Endian Defines
|
||||
* \{ */
|
||||
|
||||
#define L_ENDIAN 1
|
||||
#define B_ENDIAN 0
|
||||
#ifdef __BIG_ENDIAN__
|
||||
# define ENDIAN_ORDER B_ENDIAN
|
||||
#else
|
||||
# define ENDIAN_ORDER L_ENDIAN
|
||||
#endif
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Utility Functions
|
||||
* \{ */
|
||||
|
||||
static bool path_test_extension(const char *filepath, const char *ext)
|
||||
{
|
||||
const size_t a = strlen(filepath);
|
||||
const size_t b = strlen(ext);
|
||||
return !(a == 0 || b == 0 || b >= a) && (strcmp(ext, filepath + a - b) == 0);
|
||||
}
|
||||
|
||||
static void endian_switch_uint32(uint *val)
|
||||
{
|
||||
uint tval = *val;
|
||||
*val = (tval >> 24) | ((tval << 8) & 0x00ff0000) | ((tval >> 8) & 0x0000ff00) | (tval << 24);
|
||||
}
|
||||
|
||||
static const char *path_slash_rfind(const char *path)
|
||||
{
|
||||
const char *const lfslash = strrchr(path, '/');
|
||||
const char *const lbslash = strrchr(path, '\\');
|
||||
|
||||
if (!lfslash) {
|
||||
return lbslash;
|
||||
}
|
||||
if (!lbslash) {
|
||||
return lfslash;
|
||||
}
|
||||
|
||||
return (lfslash > lbslash) ? lfslash : lbslash;
|
||||
}
|
||||
|
||||
static const char *path_basename(const char *path)
|
||||
{
|
||||
const char *const filename = path_slash_rfind(path);
|
||||
return filename ? filename + 1 : path;
|
||||
}
|
||||
|
||||
static bool path_join(char *filepath,
|
||||
size_t filepath_maxncpy,
|
||||
const char *dirpath,
|
||||
const char *filename)
|
||||
{
|
||||
int dirpath_len = strlen(dirpath);
|
||||
if (dirpath_len && dirpath[dirpath_len - 1] == SEP) {
|
||||
dirpath_len--;
|
||||
}
|
||||
const int filename_len = strlen(filename);
|
||||
if (dirpath_len + 1 + filename_len + 1 > filepath_maxncpy) {
|
||||
return false;
|
||||
}
|
||||
memcpy(filepath, dirpath, dirpath_len);
|
||||
filepath[dirpath_len] = SEP;
|
||||
memcpy(filepath + dirpath_len + 1, filename, filename_len + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Write a PNG from RGBA Pixels
|
||||
* \{ */
|
||||
|
||||
static bool write_png(const char *filepath, const uint *pixels, const int width, const int height)
|
||||
{
|
||||
png_structp png_ptr;
|
||||
png_infop info_ptr;
|
||||
png_bytepp row_pointers = nullptr;
|
||||
|
||||
FILE *fp;
|
||||
|
||||
const int bytesperpixel = 4;
|
||||
const int compression = 9;
|
||||
int i;
|
||||
|
||||
fp = fopen(filepath, "wb");
|
||||
if (fp == nullptr) {
|
||||
printf("%s: Cannot open file for writing '%s'\n", __func__, filepath);
|
||||
return false;
|
||||
}
|
||||
|
||||
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (png_ptr == nullptr) {
|
||||
printf("%s: Cannot png_create_write_struct for file: '%s'\n", __func__, filepath);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
info_ptr = png_create_info_struct(png_ptr);
|
||||
if (info_ptr == nullptr) {
|
||||
png_destroy_write_struct(&png_ptr, (png_infopp) nullptr);
|
||||
printf("%s: Cannot png_create_info_struct for file: '%s'\n", __func__, filepath);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (setjmp(png_jmpbuf(png_ptr))) {
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
printf("%s: Cannot setjmp for file: '%s'\n", __func__, filepath);
|
||||
fclose(fp);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* write the file */
|
||||
png_init_io(png_ptr, fp);
|
||||
|
||||
png_set_compression_level(png_ptr, compression);
|
||||
|
||||
/* png image settings */
|
||||
png_set_IHDR(png_ptr,
|
||||
info_ptr,
|
||||
width,
|
||||
height,
|
||||
8,
|
||||
PNG_COLOR_TYPE_RGBA,
|
||||
PNG_INTERLACE_NONE,
|
||||
PNG_COMPRESSION_TYPE_DEFAULT,
|
||||
PNG_FILTER_TYPE_DEFAULT);
|
||||
|
||||
/* write the file header information */
|
||||
png_write_info(png_ptr, info_ptr);
|
||||
|
||||
if (ENDIAN_ORDER == L_ENDIAN) {
|
||||
png_set_swap(png_ptr);
|
||||
}
|
||||
|
||||
/* allocate memory for an array of row-pointers */
|
||||
row_pointers = (png_bytepp)malloc(height * sizeof(png_bytep));
|
||||
if (row_pointers == nullptr) {
|
||||
printf("%s: Cannot allocate row-pointers array for file '%s'\n", __func__, filepath);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* set the individual row-pointers to point at the correct offsets */
|
||||
for (i = 0; i < height; i++) {
|
||||
row_pointers[height - 1 - i] = (png_bytep)(((const uchar *)pixels) +
|
||||
(i * width) * bytesperpixel * sizeof(uchar));
|
||||
}
|
||||
|
||||
/* write out the entire image data in one call */
|
||||
png_write_image(png_ptr, row_pointers);
|
||||
|
||||
/* write the additional chunks to the PNG file (not really needed) */
|
||||
png_write_end(png_ptr, info_ptr);
|
||||
|
||||
/* clean up */
|
||||
free(row_pointers);
|
||||
png_destroy_write_struct(&png_ptr, &info_ptr);
|
||||
|
||||
fflush(fp);
|
||||
fclose(fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Merge Icon-Data from Files
|
||||
* \{ */
|
||||
|
||||
struct IconHead {
|
||||
uint icon_w, icon_h;
|
||||
uint orig_x, orig_y;
|
||||
uint canvas_w, canvas_h;
|
||||
};
|
||||
|
||||
struct IconInfo {
|
||||
IconHead head;
|
||||
char *file_name;
|
||||
};
|
||||
|
||||
struct IconMergeContext {
|
||||
/* Information about all icons read from disk.
|
||||
* Is used for sanity checks like prevention of two files defining icon for
|
||||
* the same position on canvas. */
|
||||
int num_read_icons;
|
||||
IconInfo *read_icons;
|
||||
};
|
||||
|
||||
static void icon_merge_context_init(IconMergeContext *context)
|
||||
{
|
||||
context->num_read_icons = 0;
|
||||
context->read_icons = nullptr;
|
||||
}
|
||||
|
||||
/* Get icon information from the context which matches given icon head.
|
||||
* Is used to check whether icon is re-defined, and to provide useful information about which
|
||||
* files are conflicting. */
|
||||
static IconInfo *icon_merge_context_info_for_icon_head(IconMergeContext *context,
|
||||
const IconHead *icon_head)
|
||||
{
|
||||
if (context->read_icons == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (int i = 0; i < context->num_read_icons; i++) {
|
||||
IconInfo *read_icon_info = &context->read_icons[i];
|
||||
const IconHead *read_icon_head = &read_icon_info->head;
|
||||
if (read_icon_head->orig_x == icon_head->orig_x && read_icon_head->orig_y == icon_head->orig_y)
|
||||
{
|
||||
return read_icon_info;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void icon_merge_context_register_icon(IconMergeContext *context,
|
||||
const char *file_name,
|
||||
const IconHead *icon_head)
|
||||
{
|
||||
context->read_icons = static_cast<IconInfo *>(
|
||||
realloc(context->read_icons, sizeof(IconInfo) * (context->num_read_icons + 1)));
|
||||
|
||||
IconInfo *icon_info = &context->read_icons[context->num_read_icons];
|
||||
icon_info->head = *icon_head;
|
||||
icon_info->file_name = strdup(path_basename(file_name));
|
||||
|
||||
context->num_read_icons++;
|
||||
}
|
||||
|
||||
static void icon_merge_context_free(IconMergeContext *context)
|
||||
{
|
||||
if (context->read_icons != nullptr) {
|
||||
for (int i = 0; i < context->num_read_icons; i++) {
|
||||
free(context->read_icons[i].file_name);
|
||||
}
|
||||
free(context->read_icons);
|
||||
}
|
||||
}
|
||||
|
||||
static bool icon_decode_head(FILE *f_src, IconHead *r_head)
|
||||
{
|
||||
if (fread(r_head, 1, sizeof(*r_head), f_src) == sizeof(*r_head)) {
|
||||
if (ENDIAN_ORDER == B_ENDIAN) {
|
||||
endian_switch_uint32(&r_head->icon_w);
|
||||
endian_switch_uint32(&r_head->icon_h);
|
||||
endian_switch_uint32(&r_head->orig_x);
|
||||
endian_switch_uint32(&r_head->orig_y);
|
||||
endian_switch_uint32(&r_head->canvas_w);
|
||||
endian_switch_uint32(&r_head->canvas_h);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool icon_decode(FILE *f_src, IconHead *r_head, uint **r_pixels)
|
||||
{
|
||||
uint *pixels;
|
||||
uint pixels_size;
|
||||
|
||||
if (!icon_decode_head(f_src, r_head)) {
|
||||
printf("%s: failed to read header\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
pixels_size = sizeof(char[4]) * r_head->icon_w * r_head->icon_h;
|
||||
pixels = static_cast<uint *>(malloc(pixels_size));
|
||||
if (pixels == nullptr) {
|
||||
printf("%s: failed to allocate pixels\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fread(pixels, 1, pixels_size, f_src) != pixels_size) {
|
||||
printf("%s: failed to read pixels\n", __func__);
|
||||
free(pixels);
|
||||
return false;
|
||||
}
|
||||
|
||||
*r_pixels = pixels;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool icon_read(const char *file_src, IconHead *r_head, uint **r_pixels)
|
||||
{
|
||||
FILE *f_src;
|
||||
bool success;
|
||||
|
||||
f_src = fopen(file_src, "rb");
|
||||
if (f_src == nullptr) {
|
||||
printf("%s: failed to open '%s'\n", __func__, file_src);
|
||||
return false;
|
||||
}
|
||||
|
||||
success = icon_decode(f_src, r_head, r_pixels);
|
||||
|
||||
fclose(f_src);
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool icon_merge(IconMergeContext *context,
|
||||
const char *file_src,
|
||||
uint32_t **r_pixels_canvas,
|
||||
uint *r_canvas_w,
|
||||
uint *r_canvas_h)
|
||||
{
|
||||
IconHead head;
|
||||
uint *pixels;
|
||||
|
||||
uint x, y;
|
||||
|
||||
/* canvas */
|
||||
uint32_t *pixels_canvas;
|
||||
uint canvas_w, canvas_h;
|
||||
|
||||
if (!icon_read(file_src, &head, &pixels)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const IconInfo *read_icon_info = icon_merge_context_info_for_icon_head(context, &head);
|
||||
if (read_icon_info != nullptr) {
|
||||
printf(
|
||||
"Conflicting icon files %s and %s\n", path_basename(file_src), read_icon_info->file_name);
|
||||
free(pixels);
|
||||
return false;
|
||||
}
|
||||
icon_merge_context_register_icon(context, file_src, &head);
|
||||
|
||||
if (*r_canvas_w == 0) {
|
||||
/* init once */
|
||||
*r_canvas_w = head.canvas_w;
|
||||
*r_canvas_h = head.canvas_h;
|
||||
*r_pixels_canvas = static_cast<uint32_t *>(
|
||||
calloc(1, (head.canvas_w * head.canvas_h) * sizeof(uint32_t)));
|
||||
}
|
||||
|
||||
canvas_w = *r_canvas_w;
|
||||
canvas_h = *r_canvas_h;
|
||||
pixels_canvas = *r_pixels_canvas;
|
||||
|
||||
assert(head.canvas_w == canvas_w);
|
||||
assert(head.canvas_h == canvas_h);
|
||||
|
||||
for (x = 0; x < head.icon_w; x++) {
|
||||
for (y = 0; y < head.icon_h; y++) {
|
||||
uint pixel;
|
||||
uint dst_x, dst_y;
|
||||
uint pixel_xy_dst;
|
||||
|
||||
/* get pixel */
|
||||
pixel = pixels[(y * head.icon_w) + x];
|
||||
|
||||
/* set pixel */
|
||||
dst_x = head.orig_x + x;
|
||||
dst_y = head.orig_y + y;
|
||||
pixel_xy_dst = (dst_y * canvas_w) + dst_x;
|
||||
assert(pixel_xy_dst < (canvas_w * canvas_h));
|
||||
pixels_canvas[pixel_xy_dst] = pixel;
|
||||
}
|
||||
}
|
||||
|
||||
free(pixels);
|
||||
|
||||
/* only for bounds check */
|
||||
(void)canvas_h;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool icondir_to_png(const char *path_src, const char *file_dst)
|
||||
{
|
||||
/* Takes a path full of 'dat' files and writes out */
|
||||
DIR *dir;
|
||||
const dirent *fname;
|
||||
char filepath[1024];
|
||||
int found = 0, fail = 0;
|
||||
|
||||
IconMergeContext context;
|
||||
|
||||
uint32_t *pixels_canvas = nullptr;
|
||||
uint canvas_w = 0, canvas_h = 0;
|
||||
|
||||
icon_merge_context_init(&context);
|
||||
|
||||
errno = 0;
|
||||
dir = opendir(path_src);
|
||||
if (dir == nullptr) {
|
||||
printf(
|
||||
"%s: failed to dir '%s', (%s)\n", __func__, path_src, errno ? strerror(errno) : "unknown");
|
||||
return false;
|
||||
}
|
||||
|
||||
while ((fname = readdir(dir)) != nullptr) {
|
||||
if (path_test_extension(fname->d_name, ".dat")) {
|
||||
if (!path_join(filepath, sizeof(filepath), path_src, fname->d_name)) {
|
||||
printf("%s: path is too long (%s, %s)\n", __func__, path_src, fname->d_name);
|
||||
return false;
|
||||
}
|
||||
if (icon_merge(&context, filepath, &pixels_canvas, &canvas_w, &canvas_h)) {
|
||||
found++;
|
||||
}
|
||||
else {
|
||||
fail++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
icon_merge_context_free(&context);
|
||||
|
||||
closedir(dir);
|
||||
|
||||
if (found == 0) {
|
||||
printf("%s: dir '%s' has no icons\n", __func__, path_src);
|
||||
}
|
||||
|
||||
if (fail != 0) {
|
||||
printf("%s: dir '%s' failed %d icons\n", __func__, path_src, fail);
|
||||
}
|
||||
|
||||
/* Write pixels. */
|
||||
write_png(file_dst, pixels_canvas, canvas_w, canvas_h);
|
||||
|
||||
free(pixels_canvas);
|
||||
|
||||
return (fail == 0);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Main & Parse Arguments
|
||||
* \{ */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *path_src;
|
||||
const char *file_dst;
|
||||
|
||||
if (argc < 3) {
|
||||
printf("Usage: datatoc_icon <dir_icons> <data_icon_to.png>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
path_src = argv[1];
|
||||
file_dst = argv[2];
|
||||
|
||||
return (icondir_to_png(path_src, file_dst) == true) ? 0 : 1;
|
||||
}
|
||||
|
||||
/** \} */
|
@ -1,146 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-FileCopyrightText: 2014-2022 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
_IS_BIG_ENDIAN = (__import__("sys").byteorder != 'little')
|
||||
|
||||
|
||||
def write_png(buf, width, height):
|
||||
import zlib
|
||||
import struct
|
||||
# reverse the vertical line order and add null bytes at the start
|
||||
width_byte_4 = width * 4
|
||||
raw_data = b"".join(
|
||||
b'\x00' + buf[span:span + width_byte_4]
|
||||
for span in range((height - 1) * width * 4, -1, - width_byte_4)
|
||||
)
|
||||
|
||||
def png_pack(png_tag, data):
|
||||
chunk_head = png_tag + data
|
||||
return struct.pack("!I", len(data)) + chunk_head + struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head))
|
||||
|
||||
return b"".join([
|
||||
b'\x89PNG\r\n\x1a\n',
|
||||
png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
|
||||
png_pack(b'IDAT', zlib.compress(raw_data, 9)),
|
||||
png_pack(b'IEND', b'')])
|
||||
|
||||
|
||||
def icon_decode_head(f_src):
|
||||
import struct
|
||||
|
||||
# 2 ints
|
||||
temp_data = f_src.read(4 * 2)
|
||||
icon_w, icon_h = struct.unpack('<2I', temp_data)
|
||||
|
||||
temp_data = f_src.read(4 * 2)
|
||||
orig_x, orig_y = struct.unpack('<2I', temp_data)
|
||||
|
||||
temp_data = f_src.read(4 * 2)
|
||||
canvas_w, canvas_h = struct.unpack('<2I', temp_data)
|
||||
|
||||
return (icon_w, icon_h,
|
||||
orig_x, orig_y,
|
||||
canvas_w, canvas_h)
|
||||
|
||||
|
||||
def icon_decode(f_src):
|
||||
head = icon_decode_head(f_src)
|
||||
|
||||
(icon_w, icon_h,
|
||||
orig_x, orig_y,
|
||||
canvas_w, canvas_h) = head
|
||||
|
||||
# pixels
|
||||
import array
|
||||
|
||||
pixels = f_src.read(icon_w * icon_h * 4)
|
||||
pixels = array.array('I', pixels)
|
||||
if _IS_BIG_ENDIAN:
|
||||
pixels.byteswap()
|
||||
|
||||
return head, pixels
|
||||
|
||||
|
||||
def icon_read(file_src):
|
||||
with open(file_src, 'rb') as f_src:
|
||||
head, pixels = icon_decode(f_src)
|
||||
return head, pixels
|
||||
|
||||
|
||||
def icon_merge(file_src, pixels_canvas, canvas_w, canvas_h):
|
||||
""" Takes an icon filepath and merges into a pixel array
|
||||
"""
|
||||
head, pixels = icon_read(file_src)
|
||||
|
||||
(icon_w, icon_h,
|
||||
orig_x, orig_y,
|
||||
w_canvas_test, h_canvas_test) = head
|
||||
|
||||
assert w_canvas_test == canvas_w
|
||||
assert h_canvas_test == canvas_h
|
||||
|
||||
for x in range(icon_w):
|
||||
for y in range(icon_h):
|
||||
# get pixel
|
||||
pixel = pixels[(y * icon_w) + x]
|
||||
|
||||
# set pixel
|
||||
dst_x = orig_x + x
|
||||
dst_y = orig_y + y
|
||||
pixels_canvas[(dst_y * canvas_w) + dst_x] = pixel
|
||||
|
||||
|
||||
def icondir_to_png(path_src, file_dst):
|
||||
""" Takes a path full of 'dat' files and writes out
|
||||
"""
|
||||
import os
|
||||
import array
|
||||
|
||||
files = [os.path.join(path_src, f) for f in os.listdir(path_src) if f.endswith(".dat")]
|
||||
|
||||
# First check if we need to bother.
|
||||
if os.path.exists(file_dst):
|
||||
dst_time = os.path.getmtime(file_dst)
|
||||
has_newer = False
|
||||
for f in files:
|
||||
if os.path.getmtime(f) > dst_time:
|
||||
has_newer = True
|
||||
break
|
||||
if not has_newer:
|
||||
return
|
||||
|
||||
with open(files[0], 'rb') as f_src:
|
||||
(icon_w, icon_h,
|
||||
orig_x, orig_y,
|
||||
canvas_w, canvas_h) = icon_decode_head(f_src)
|
||||
|
||||
# load in pixel data
|
||||
pixels_canvas = array.array('I', [0]) * (canvas_w * canvas_h)
|
||||
for f in files:
|
||||
icon_merge(f, pixels_canvas, canvas_w, canvas_h)
|
||||
|
||||
# write pixels
|
||||
with open(file_dst, 'wb') as f_dst:
|
||||
pixels_data = pixels_canvas.tobytes()
|
||||
image_data = write_png(pixels_data, canvas_w, canvas_h)
|
||||
f_dst.write(image_data)
|
||||
|
||||
|
||||
def main_ex(argv):
|
||||
import os
|
||||
|
||||
path_src = argv[-2].rstrip(os.sep)
|
||||
file_dst = argv[-1]
|
||||
|
||||
icondir_to_png(path_src, file_dst)
|
||||
|
||||
|
||||
def main():
|
||||
import sys
|
||||
main_ex(sys.argv)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,302 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2014-2022 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
"""
|
||||
This script dices up PNG into small files to store in version control.
|
||||
|
||||
Example:
|
||||
|
||||
./blender.bin \
|
||||
--background \
|
||||
--python ./release/datafiles/icon_dice.py -- \
|
||||
--image=./release/datafiles/blender_icons16.png \
|
||||
--output=./release/datafiles/blender_icons16
|
||||
--output_prefix=icon16_
|
||||
--name_style=UI_ICONS
|
||||
--parts_x 26 --parts_y 32 \
|
||||
--minx=10 --maxx 10 --miny 10 --maxy 10
|
||||
--minx_icon 2 --maxx_icon 2 --miny_icon 2 --maxy_icon 2 \
|
||||
--spacex_icon 1 --spacey_icon 1
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
SOURCE_DIR = os.path.normpath(os.path.join(os.path.dirname(__file__), "..", "..", ".."))
|
||||
VERBOSE = False
|
||||
|
||||
|
||||
def image_from_file__bpy(filepath):
|
||||
import bpy
|
||||
|
||||
image = bpy.data.images.load(filepath)
|
||||
image.reload()
|
||||
|
||||
pixel_w, pixel_h = image.size
|
||||
pixels = image.pixels[:]
|
||||
return pixels, pixel_w, pixel_h
|
||||
|
||||
|
||||
def image_from_file(filepath):
|
||||
"""
|
||||
Return pixels, w, h from an image.
|
||||
|
||||
note: bpy import is ONLY used here.
|
||||
"""
|
||||
|
||||
try:
|
||||
import bpy
|
||||
except ImportError:
|
||||
bpy = None
|
||||
|
||||
if bpy is not None:
|
||||
pixels, pixel_w, pixel_h = image_from_file__bpy(filepath)
|
||||
# else:
|
||||
# pixels, pixel_w, pixel_h = image_from_file__py(filepath)
|
||||
|
||||
return pixels, pixel_w, pixel_h
|
||||
|
||||
|
||||
def write_subimage(sub_x, sub_y, sub_w, sub_h,
|
||||
filepath,
|
||||
pixels, pixel_w, pixel_h):
|
||||
import struct
|
||||
|
||||
# first check if the icon is worth writing
|
||||
is_fill = False
|
||||
for y in range(sub_h):
|
||||
for x in range(sub_w):
|
||||
i = (sub_x + x) + ((sub_y + y) * pixel_w)
|
||||
a = pixels[(i * 4) + 3]
|
||||
if a != 0.0:
|
||||
is_fill = True
|
||||
break
|
||||
|
||||
if not is_fill:
|
||||
# print("skipping:", filepath)
|
||||
return
|
||||
|
||||
with open(filepath, 'wb') as f:
|
||||
|
||||
f.write(
|
||||
struct.pack(
|
||||
'<6I',
|
||||
sub_w, sub_h,
|
||||
sub_x, sub_y,
|
||||
# redundant but including to maintain consistency
|
||||
pixel_w, pixel_h,
|
||||
))
|
||||
|
||||
for y in range(sub_h):
|
||||
for x in range(sub_w):
|
||||
i = (sub_x + x) + ((sub_y + y) * pixel_w)
|
||||
rgba = pixels[(i * 4):(i * 4) + 4]
|
||||
c = sum((int(p * 255) << (8 * i)) for i, p in enumerate(rgba))
|
||||
f.write(struct.pack("<I", c))
|
||||
|
||||
|
||||
_dice_icon_name_cache = {}
|
||||
|
||||
|
||||
def dice_icon_name(
|
||||
x, y, parts_x, parts_y,
|
||||
name_style=None, prefix=""):
|
||||
"""
|
||||
How to name icons, this is mainly for what name we get in git,
|
||||
the actual names don't really matter, its just nice to have the
|
||||
name match up with something recognizable for commits.
|
||||
"""
|
||||
if name_style == 'UI_ICONS':
|
||||
|
||||
# Init on demand
|
||||
if not _dice_icon_name_cache:
|
||||
import re
|
||||
count = 0
|
||||
|
||||
# Search for eg: DEF_ICON(BRUSH_NUDGE) --> BRUSH_NUDGE
|
||||
re_icon = re.compile(r'^\s*DEF_ICON.*\(\s*([A-Za-z0-9_]+)\s*\).*$')
|
||||
|
||||
ui_icons_h = os.path.join(SOURCE_DIR, "source", "blender", "editors", "include", "UI_icons.hh")
|
||||
with open(ui_icons_h, 'r', encoding="utf-8") as f:
|
||||
for l in f:
|
||||
match = re_icon.search(l)
|
||||
if match:
|
||||
if l.find('DEF_ICON_BLANK') == -1:
|
||||
icon_name = match.group(1).lower()
|
||||
print(icon_name)
|
||||
_dice_icon_name_cache[count] = icon_name
|
||||
count += 1
|
||||
# ---- Done with icon cache
|
||||
|
||||
index = (y * parts_x) + x
|
||||
if index not in _dice_icon_name_cache:
|
||||
return None
|
||||
|
||||
icon_name = _dice_icon_name_cache[index]
|
||||
|
||||
# for debugging its handy to sort by number
|
||||
# ~ id_str = "%03d_%s%s.dat" % (index, prefix, icon_name)
|
||||
|
||||
id_str = "%s%s.dat" % (prefix, icon_name)
|
||||
|
||||
elif name_style == "":
|
||||
# flip so icons are numbered from top-left
|
||||
# because new icons will be added at the bottom
|
||||
y_flip = parts_y - (y + 1)
|
||||
id_str = "%s%02xx%02x.dat" % (prefix, x, y_flip)
|
||||
else:
|
||||
raise Exception("Invalid '--name_style' arg")
|
||||
|
||||
return id_str
|
||||
|
||||
|
||||
def dice(
|
||||
filepath, output, output_prefix, name_style,
|
||||
parts_x, parts_y,
|
||||
minx, miny, maxx, maxy,
|
||||
minx_icon, miny_icon, maxx_icon, maxy_icon,
|
||||
spacex_icon, spacey_icon,
|
||||
):
|
||||
|
||||
is_simple = (max(
|
||||
minx, miny, maxx, maxy,
|
||||
minx_icon, miny_icon, maxx_icon, maxy_icon,
|
||||
spacex_icon, spacey_icon) == 0)
|
||||
|
||||
pixels, pixel_w, pixel_h = image_from_file(filepath)
|
||||
|
||||
if not (pixel_w and pixel_h):
|
||||
print("Image not found %r!" % filepath)
|
||||
return
|
||||
|
||||
if not os.path.exists(output):
|
||||
os.mkdir(output)
|
||||
|
||||
if is_simple:
|
||||
pixels_w_clip = pixel_w
|
||||
pixels_h_clip = pixel_h
|
||||
|
||||
icon_w = pixels_w_clip // parts_x
|
||||
icon_h = pixels_h_clip // parts_y
|
||||
icon_w_clip = icon_w
|
||||
icon_h_clip = icon_h
|
||||
else:
|
||||
pixels_w_clip = pixel_w - (minx + maxx)
|
||||
pixels_h_clip = pixel_h - (miny + maxy)
|
||||
|
||||
icon_w = (pixels_w_clip - ((parts_x - 1) * spacex_icon)) // parts_x
|
||||
icon_h = (pixels_h_clip - ((parts_y - 1) * spacey_icon)) // parts_y
|
||||
icon_w_clip = icon_w - (minx_icon + maxx_icon)
|
||||
icon_h_clip = icon_h - (miny_icon + maxy_icon)
|
||||
|
||||
print(pixel_w, pixel_h, icon_w, icon_h)
|
||||
|
||||
for x in range(parts_x):
|
||||
for y in range(parts_y):
|
||||
id_str = dice_icon_name(
|
||||
x, y,
|
||||
parts_x, parts_y,
|
||||
name_style=name_style, prefix=output_prefix,
|
||||
)
|
||||
if not id_str:
|
||||
continue
|
||||
|
||||
filepath = os.path.join(output, id_str)
|
||||
if VERBOSE:
|
||||
print(" writing:", filepath)
|
||||
|
||||
# simple, no margins
|
||||
if is_simple:
|
||||
sub_x = x * icon_w
|
||||
sub_y = y * icon_h
|
||||
else:
|
||||
sub_x = minx + ((x * (icon_w + spacex_icon)) + minx_icon)
|
||||
sub_y = miny + ((y * (icon_h + spacey_icon)) + miny_icon)
|
||||
|
||||
write_subimage(sub_x, sub_y, icon_w_clip, icon_h_clip,
|
||||
filepath,
|
||||
pixels, pixel_w, pixel_h)
|
||||
|
||||
|
||||
def main():
|
||||
import sys
|
||||
import argparse
|
||||
|
||||
epilog = "Run this after updating the SVG file"
|
||||
|
||||
argv = sys.argv
|
||||
|
||||
if "--" not in argv:
|
||||
argv = []
|
||||
else:
|
||||
argv = argv[argv.index("--") + 1:]
|
||||
|
||||
parser = argparse.ArgumentParser(description=__doc__, epilog=epilog)
|
||||
|
||||
# File path options
|
||||
parser.add_argument(
|
||||
"--image", dest="image", metavar='FILE',
|
||||
help="Image file",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output", dest="output", metavar='DIR',
|
||||
help="Output directory",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--output_prefix", dest="output_prefix", metavar='STRING',
|
||||
help="Output prefix",
|
||||
)
|
||||
|
||||
# Icon naming option
|
||||
parser.add_argument(
|
||||
"--name_style", dest="name_style", metavar='ENUM', type=str,
|
||||
choices=('', 'UI_ICONS'),
|
||||
help="The method used for naming output data",
|
||||
)
|
||||
|
||||
# Options for dicing up the image
|
||||
parser.add_argument(
|
||||
"--parts_x", dest="parts_x", metavar='INT', type=int,
|
||||
help="Grid X parts",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--parts_y", dest="parts_y", metavar='INT', type=int,
|
||||
help="Grid Y parts",
|
||||
)
|
||||
|
||||
_help = "Inset from the outer edge (in pixels)"
|
||||
parser.add_argument("--minx", dest="minx", metavar='INT', type=int, help=_help)
|
||||
parser.add_argument("--miny", dest="miny", metavar='INT', type=int, help=_help)
|
||||
parser.add_argument("--maxx", dest="maxx", metavar='INT', type=int, help=_help)
|
||||
parser.add_argument("--maxy", dest="maxy", metavar='INT', type=int, help=_help)
|
||||
|
||||
_help = "Inset from each icons bounds (in pixels)"
|
||||
parser.add_argument("--minx_icon", dest="minx_icon", metavar='INT', type=int, help=_help)
|
||||
parser.add_argument("--miny_icon", dest="miny_icon", metavar='INT', type=int, help=_help)
|
||||
parser.add_argument("--maxx_icon", dest="maxx_icon", metavar='INT', type=int, help=_help)
|
||||
parser.add_argument("--maxy_icon", dest="maxy_icon", metavar='INT', type=int, help=_help)
|
||||
|
||||
_help = "Empty space between icons"
|
||||
parser.add_argument("--spacex_icon", dest="spacex_icon", metavar='INT', type=int, help=_help)
|
||||
parser.add_argument("--spacey_icon", dest="spacey_icon", metavar='INT', type=int, help=_help)
|
||||
|
||||
del _help
|
||||
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
if not argv:
|
||||
print("No args given!")
|
||||
parser.print_help()
|
||||
return
|
||||
|
||||
dice(args.image, args.output, args.output_prefix, args.name_style,
|
||||
args.parts_x, args.parts_y,
|
||||
args.minx, args.miny, args.maxx, args.maxy,
|
||||
args.minx_icon, args.miny_icon, args.maxx_icon, args.maxy_icon,
|
||||
args.spacex_icon, args.spacey_icon,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -1,60 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-FileCopyrightText: 2014-2022 Blender Authors
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# This script is just to view the icons
|
||||
|
||||
|
||||
def write_png(buf, width, height):
|
||||
import zlib
|
||||
import struct
|
||||
# reverse the vertical line order and add null bytes at the start
|
||||
width_byte_4 = width * 4
|
||||
raw_data = b"".join(
|
||||
b'\x00' + buf[span:span + width_byte_4]
|
||||
for span in range((height - 1) * width * 4, -1, - width_byte_4)
|
||||
)
|
||||
|
||||
def png_pack(png_tag, data):
|
||||
chunk_head = png_tag + data
|
||||
return struct.pack("!I", len(data)) + chunk_head + struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head))
|
||||
|
||||
return b"".join([
|
||||
b'\x89PNG\r\n\x1a\n',
|
||||
png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)),
|
||||
png_pack(b'IDAT', zlib.compress(raw_data, 9)),
|
||||
png_pack(b'IEND', b'')])
|
||||
|
||||
|
||||
def icondata_to_png(file_src, file_dst):
|
||||
import struct
|
||||
|
||||
with open(file_src, 'rb') as f_src:
|
||||
# 2 ints
|
||||
temp_data = f_src.read(4 * 2)
|
||||
w, h = struct.unpack('<2I', temp_data)
|
||||
temp_data = f_src.read(4 * 2) # (x, y) - ignored
|
||||
temp_data = f_src.read(4 * 2) # (xfrom, yfrom) - ignored
|
||||
# pixels
|
||||
temp_data = f_src.read(w * h * 4)
|
||||
|
||||
buf = write_png(temp_data, w, h)
|
||||
|
||||
with open(file_dst, 'wb') as f_dst:
|
||||
f_dst.write(buf)
|
||||
|
||||
|
||||
def main():
|
||||
import sys
|
||||
import os
|
||||
|
||||
for arg in sys.argv[1:]:
|
||||
file_src = arg
|
||||
file_dst = os.path.splitext(arg)[0] + ".png"
|
||||
|
||||
icondata_to_png(file_src, file_dst)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
Loading…
Reference in New Issue
Block a user