diff --git a/CMakeLists.txt b/CMakeLists.txt index e061918cd..3f613918c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -213,7 +213,7 @@ file(GLOB COMPATSRC CONFIGURE_DEPENDS src/compat/*.c) ############################################################################ # libnotcurses-core (core shared library, core static library) -file(GLOB NCCORESRCS CONFIGURE_DEPENDS src/lib/*.c src/lib/*.cpp) +file(GLOB NCCORESRCS CONFIGURE_DEPENDS src/lib/*.c) add_library(notcurses-core SHARED ${NCCORESRCS} ${COMPATSRC}) if(${USE_STATIC}) add_library(notcurses-core-static STATIC ${NCCORESRCS} ${COMPATSRC}) @@ -408,6 +408,57 @@ target_link_directories(notcurses PRIVATE ${OIIO_LIBRARY_DIRS}) target_link_directories(notcurses-static PRIVATE ${OIIO_STATIC_LIBRARY_DIRS}) endif() +############################################################################ +# libncsixel (sixel library built atop notcurses) +file(GLOB NCSIXSRCS CONFIGURE_DEPENDS src/sixel/*.c) +add_library(ncsixel SHARED ${NCSIXSRCS} ${COMPATSRC}) +if(${USE_STATIC}) +add_library(ncsixel-static STATIC ${NCSIXSRCS}) +else() +add_library(ncsixel-static STATIC EXCLUDE_FROM_ALL ${NCSIXSRCS}) +endif() +set_target_properties(ncsixel PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} +) +set_target_properties(ncsixel-static PROPERTIES + VERSION ${PROJECT_VERSION} + OUTPUT_NAME ncsixel +) +target_include_directories(ncsixel + BEFORE + PRIVATE + include + src + "${CMAKE_REQUIRED_INCLUDES}" + "${PROJECT_BINARY_DIR}/include" + "${TERMINFO_INCLUDE_DIRS}" +) +target_include_directories(ncsixel-static + BEFORE + PRIVATE + include + src + "${CMAKE_REQUIRED_INCLUDES}" + "${PROJECT_BINARY_DIR}/include" + "${TERMINFO_INCLUDE_DIRS}" +) +target_compile_definitions(ncsixel + PRIVATE + _GNU_SOURCE _DEFAULT_SOURCE +) +target_compile_definitions(ncsixel-static + PRIVATE + _GNU_SOURCE _DEFAULT_SOURCE +) +target_link_libraries(ncsixel + PUBLIC + notcurses +) +target_link_libraries(ncsixel-static + PUBLIC + notcurses-static +) ############################################################################ if(${USE_CXX}) # libnotcurses++ (C++ wrappers) diff --git a/include/sixel/sixel.h b/include/sixel/sixel.h index e00e54f6a..fded7d11b 100644 --- a/include/sixel/sixel.h +++ b/include/sixel/sixel.h @@ -1,6 +1,9 @@ #ifndef NOTCURSES_SIXEL_SIXEL #define NOTCURSES_SIXEL_SIXEL +// a library built atop Notcurses suitable for working with sixels outside +// the Notcurses framework--a replacement for libsixel. + #ifdef __cplusplus extern "C" { #define RESTRICT @@ -15,7 +18,19 @@ extern "C" { #endif #define ALLOC __attribute__((malloc)) __attribute__((warn_unused_result)) -// FIXME libsixel-like API +struct sixel; +struct sixelctx; + +API ALLOC struct sixelctx* libncsixel_init(void); + +// load the file and encode the first frame as a sixel. if |colorregs| is 0, +// use the number supported by the terminal, or 256 if the terminal does not +// support sixel. +API ALLOC __attribute__ ((nonnull (1, 2))) +struct sixel* libncsixel_encode(struct sixelctx* sctx, const char* file, + unsigned colorregs); + +API void libncsixel_stop(struct sixelctx* sctx); #undef API #undef ALLOC diff --git a/src/sixel/sixel.c b/src/sixel/sixel.c new file mode 100644 index 000000000..2b25d649d --- /dev/null +++ b/src/sixel/sixel.c @@ -0,0 +1,51 @@ +#include "sixel/sixel.h" +#include + +// represents a sixel generated from some image +typedef struct sixel { + char* escape; // nul-terminated escape suitable for writing to the terminal + // there is both the true pixel geometry, and the sprixel-padded pixel + // geometry--the latter always has a height which is a multiple of six. + unsigned pixy, pixx; // original pixel geometry + unsigned sprixpixy, sprixpixx; // sprixel-padded pixel geometry + // we might only occupy a portion of the final column and row of cells. + unsigned celly, cellx; // cell geometry + unsigned colorregs_avail; // color registers available + unsigned colorregs_used; // color registers used +} sixel; + +typedef struct sixelctx { + struct notcurses* nc; +} sixelctx; + +sixelctx* libncsixel_init(void){ + sixelctx* sctx = malloc(sizeof(*sctx)); + if(sctx == NULL){ + return NULL; + } + struct notcurses_options nopts = { + .flags = NCOPTION_NO_ALTERNATE_SCREEN | + NCOPTION_PRESERVE_CURSOR | + NCOPTION_SUPPRESS_BANNERS | + NCOPTION_DRAIN_INPUT, + }; + if((sctx->nc = notcurses_init(&nopts, NULL)) == NULL){ + free(sctx); + return NULL; + } + return sctx; +} + +sixel* libncsixel_encode(sixelctx* sctx, const char* file, unsigned colorregs){ + (void)sctx; + (void)file; + (void)colorregs; + return NULL; +} + +void libncsixel_stop(sixelctx* sctx){ + if(sctx){ + notcurses_stop(sctx->nc); + free(sctx); + } +}