From 59eae5643ee3c49ad25b1fc36671391940a15545 Mon Sep 17 00:00:00 2001 From: Kim Woelders Date: Fri, 8 Apr 2022 08:11:39 +0200 Subject: [PATCH] Add PS/EPS loader using libspectre --- configure.ac | 2 + src/lib/loaders.c | 6 ++ src/modules/loaders/Makefile.am | 9 ++ src/modules/loaders/loader_ps.c | 147 ++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+) create mode 100644 src/modules/loaders/loader_ps.c diff --git a/configure.ac b/configure.ac index c2b59db..65b8bad 100644 --- a/configure.ac +++ b/configure.ac @@ -199,6 +199,7 @@ EC_LOADER_CHECK(JPEG, auto, libjpeg) EC_LOADER_CHECK(J2K, auto, libopenjp2) EC_LOADER_CHECK(JXL, auto, libjxl libjxl_threads) EC_LOADER_CHECK(PNG, auto, libpng) +EC_LOADER_CHECK(PS, auto, libspectre) EC_LOADER_CHECK(SVG, auto, librsvg-2.0 >= 2.46) EC_LOADER_CHECK(TIFF, auto, libtiff-4) EC_LOADER_CHECK(WEBP, auto, libwebpdemux) @@ -288,6 +289,7 @@ echo " JPEG....................: $jpeg_ok" echo " J2K.....................: $j2k_ok" echo " JXL.....................: $jxl_ok" echo " PNG.....................: $png_ok" +echo " PS......................: $ps_ok" echo " SVG.....................: $svg_ok" echo " TIFF....................: $tiff_ok" echo " WEBP....................: $webp_ok" diff --git a/src/lib/loaders.c b/src/lib/loaders.c index c6098ed..dd89356 100644 --- a/src/lib/loaders.c +++ b/src/lib/loaders.c @@ -48,6 +48,9 @@ static const char *const ext_png[] = { "png", NULL }; #endif static const char *const ext_pnm[] = { "pnm", "ppm", "pgm", "pbm", "pam", NULL }; +#ifdef BUILD_PS_LOADER +static const char *const ext_ps[] = { "ps", "eps", NULL }; +#endif #ifdef BUILD_SVG_LOADER static const char *const ext_svg[] = { "svg", NULL }; #endif @@ -98,6 +101,9 @@ static const KnownLoader loaders_known[] = { {"lbm", ext_lbm}, #ifdef BUILD_PNG_LOADER {"png", ext_png}, +#endif +#ifdef BUILD_PS_LOADER + {"ps", ext_ps}, #endif {"pnm", ext_pnm}, #ifdef BUILD_SVG_LOADER diff --git a/src/modules/loaders/Makefile.am b/src/modules/loaders/Makefile.am index cdd637c..82031fa 100644 --- a/src/modules/loaders/Makefile.am +++ b/src/modules/loaders/Makefile.am @@ -32,6 +32,9 @@ endif if BUILD_PNG_LOADER pkg_LTLIBRARIES += png.la endif +if BUILD_PS_LOADER +pkg_LTLIBRARIES += ps.la +endif if BUILD_SVG_LOADER pkg_LTLIBRARIES += svg.la endif @@ -123,6 +126,12 @@ pnm_la_LDFLAGS = -module -avoid-version pnm_la_LIBADD = $(top_builddir)/src/lib/libImlib2.la pnm_la_LIBTOOLFLAGS = --tag=disable-static +ps_la_SOURCES = loader_ps.c +ps_la_CPPFLAGS = $(PS_CFLAGS) $(AM_CPPFLAGS) +ps_la_LDFLAGS = -module -avoid-version +ps_la_LIBADD = $(PS_LIBS) $(top_builddir)/src/lib/libImlib2.la +ps_la_LIBTOOLFLAGS = --tag=disable-static + svg_la_SOURCES = loader_svg.c svg_la_CPPFLAGS = $(SVG_CFLAGS) $(AM_CPPFLAGS) svg_la_LDFLAGS = -module -avoid-version -Wl,-z,nodelete diff --git a/src/modules/loaders/loader_ps.c b/src/modules/loaders/loader_ps.c new file mode 100644 index 0000000..717220f --- /dev/null +++ b/src/modules/loaders/loader_ps.c @@ -0,0 +1,147 @@ +#include "loader_common.h" + +#include + +#define DBG_PFX "LDR-ps" + +int +load2(ImlibImage * im, int load_data) +{ + int rc; + void *fdata; + SpectreDocument *spdoc; + SpectrePage *sppage; + SpectreStatus spst; + int frame; + int w, h; + SpectreRenderContext *sprc; + unsigned char *pdata; + int rowlen; + unsigned char *src; + uint32_t *dst; + int i, j; + + fdata = mmap(NULL, im->fsize, PROT_READ, MAP_SHARED, fileno(im->fp), 0); + if (fdata == MAP_FAILED) + return LOAD_BADFILE; + + rc = LOAD_FAIL; + spdoc = NULL; + sppage = NULL; + sprc = NULL; + + /* Signature check */ + if (memcmp(fdata, "%!PS", 4) != 0) + goto quit; + + spdoc = spectre_document_new(); + if (!spdoc) + goto quit; + + spectre_document_load(spdoc, im->real_file); + spst = spectre_document_status(spdoc); + if (spst != SPECTRE_STATUS_SUCCESS) + { + D("spectre_document_load: %s\n", spectre_status_to_string(spst)); + goto quit; + } + + rc = LOAD_BADIMAGE; /* Format accepted */ + + frame = 1; + if (im->frame_num > 0) + { + frame = im->frame_num; + im->frame_count = spectre_document_get_n_pages(spdoc); + D("Pages=%d\n", im->frame_count); + + if (frame > 1 && frame > im->frame_count) + QUIT_WITH_RC(LOAD_BADFRAME); + } + + sppage = spectre_document_get_page(spdoc, frame - 1); + spst = spectre_document_status(spdoc); + if (spst != SPECTRE_STATUS_SUCCESS) + { + D("spectre_document_get_page: %s\n", spectre_status_to_string(spst)); + goto quit; + } + + spectre_page_get_size(sppage, &w, &h); + + D("WxH=%dx%d pages=%d fmt=%s level=%d eps=%d\n", w, h, im->frame_count, + spectre_document_get_format(spdoc), + spectre_document_get_language_level(spdoc), + spectre_document_is_eps(spdoc)); + im->w = im->canvas_w = w; + im->h = im->canvas_h = h; + + if (!IMAGE_DIMENSIONS_OK(im->w, im->h)) + goto quit; + + if (!load_data) + QUIT_WITH_RC(LOAD_SUCCESS); + + /* Load data */ + + if (!__imlib_AllocateData(im)) + QUIT_WITH_RC(LOAD_OOM); + + sprc = spectre_render_context_new(); + if (!sprc) + QUIT_WITH_RC(LOAD_OOM); + + rowlen = 0; + spectre_page_render(sppage, sprc, &pdata, &rowlen); + spst = spectre_page_status(sppage); + if (spst != SPECTRE_STATUS_SUCCESS) + { + D("spectre_render_context_set_page_size: %s\n", + spectre_status_to_string(spst)); + goto quit; + } + + spectre_render_context_set_page_size(sprc, im->w, im->h); + spst = spectre_page_status(sppage); + if (spst != SPECTRE_STATUS_SUCCESS) + { + D("spectre_render_context_set_page_size: %s\n", + spectre_status_to_string(spst)); + goto quit; + } + + src = pdata; + dst = im->data; + + D("rowlen=%d (%d)\n", rowlen, 4 * im->w); + + for (i = 0; i < im->h; i++) + { + src = pdata + i * rowlen; + for (j = 0; j < im->w; j++, src += 4) + *dst++ = PIXEL_ARGB(0xff, src[2], src[1], src[0]); + + if (im->lc && __imlib_LoadProgressRows(im, i, 1)) + QUIT_WITH_RC(LOAD_BREAK); + } + + rc = LOAD_SUCCESS; + + quit: + if (sprc) + spectre_render_context_free(sprc); + if (sppage) + spectre_page_free(sppage); + if (spdoc) + spectre_document_free(spdoc); + munmap(fdata, im->fsize); + + return rc; +} + +void +formats(ImlibLoader * l) +{ + static const char *const list_formats[] = { "ps", "eps" }; + __imlib_LoaderSetFormats(l, list_formats, ARRAY_SIZE(list_formats)); +}