aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/de.marvinborner.zathura-note.metainfo.xml1
-rw-r--r--license13
-rw-r--r--meson.build5
-rw-r--r--zathura-note/cairo_jpg.c612
-rw-r--r--zathura-note/cairo_jpg.h75
-rw-r--r--zathura-note/note.c139
6 files changed, 117 insertions, 728 deletions
diff --git a/data/de.marvinborner.zathura-note.metainfo.xml b/data/de.marvinborner.zathura-note.metainfo.xml
index 8958e32..3ca7771 100644
--- a/data/de.marvinborner.zathura-note.metainfo.xml
+++ b/data/de.marvinborner.zathura-note.metainfo.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="addon">
<id>de.marvinborner.zathura-note</id>
+ <project_license>WTFPL</project_license>
<extends>org.pwmt.zathura</extends>
<name>Zathura-note</name>
<summary>Notability .note support for zathura</summary>
diff --git a/license b/license
new file mode 100644
index 0000000..b01085e
--- /dev/null
+++ b/license
@@ -0,0 +1,13 @@
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ Version 2, December 2004
+
+Copyright (C) 2021 Marvin Borner <develop@marvinborner.de>
+
+Everyone is permitted to copy and distribute verbatim or modified
+copies of this license document, and changing it is allowed as long
+as the name is changed.
+
+ DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. You just DO WHAT THE FUCK YOU WANT TO.
diff --git a/meson.build b/meson.build
index 5683db2..8f7647f 100644
--- a/meson.build
+++ b/meson.build
@@ -21,7 +21,6 @@ glib = dependency('glib-2.0')
cairo = dependency('cairo')
zip = dependency('libzip')
plist = dependency('libplist')
-jpeg = dependency('libjpeg')
build_dependencies = [
zathura,
@@ -29,8 +28,7 @@ build_dependencies = [
glib,
cairo,
zip,
- plist,
- jpeg
+ plist
]
plugindir = zathura.get_pkgconfig_variable('plugindir')
@@ -55,7 +53,6 @@ flags = [
flags = cc.get_supported_arguments(flags)
sources = files(
- 'zathura-note/cairo_jpg.c',
'zathura-note/plugin.c',
'zathura-note/note.c'
)
diff --git a/zathura-note/cairo_jpg.c b/zathura-note/cairo_jpg.c
deleted file mode 100644
index cd47f20..0000000
--- a/zathura-note/cairo_jpg.c
+++ /dev/null
@@ -1,612 +0,0 @@
-/* Copyright 2018 Bernhard R. Fischer, 4096R/8E24F29D <bf@abenteuerland.at>
- *
- * This file is part of Cairo_JPG.
- *
- * Cairo_JPG is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Cairo_JPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Cairo_JPG. If not, see <https://www.gnu.org/licenses/>.
- */
-
-/*! \file cairo_jpg.c
- * This file contains two functions for reading and writing JPEG files from
- * and to Cairo image surfaces. It uses the functions from the libjpeg.
- * Most of the code is directly derived from the online example at
- * http://libjpeg-turbo.virtualgl.org/Documentation/Documentation
- *
- * All prototypes are defined in cairo_jpg.h All functions and their parameters
- * and return values are described below directly at the functions. You may
- * also have a look at the preprocessor macros defined below.
- *
- * To compile this code you need to have installed the packages libcairo2-dev
- * and libjpeg-dev. Compile with the following to create an object file to link
- * with your code:
- * gcc -std=c99 -Wall -c `pkg-config cairo libjpeg --cflags --libs` cairo_jpg.c
- * Use the following command to include the main() function and create an
- * executable for testing of this code:
- * gcc -std=c99 -Wall -o cairo_jpg -DCAIRO_JPEG_MAIN `pkg-config cairo libjpeg --cflags --libs` cairo_jpg.c
- *
- * @author Bernhard R. Fischer, 4096R/8E24F29D bf@abenteuerland.at
- * @version 2020/01/18
- * @license LGPL3.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <cairo.h>
-#include <jpeglib.h>
-
-#include "cairo_jpg.h"
-
-/*! Macro to activate main() function. This is only used for testing. Comment
- * it out (#undef) if you link this file to your own program.
- */
-//#define CAIRO_JPEG_MAIN
-//
-/*! Define this to use an alternate implementation of
- * cairo_image_surface_create_from_jpeg() which fstat(3)s the file before
- * reading (see below). For huge files this /may/ be slightly faster.
- */
-#undef CAIRO_JPEG_USE_FSTAT
-
-/*! This is the read block size for the stream reader
- * cairo_image_surface_create_from_jpeg_stream().
- */
-#ifdef USE_CAIRO_READ_FUNC_LEN_T
-#define CAIRO_JPEG_IO_BLOCK_SIZE 4096
-#else
-/*! Block size has to be one if cairo_read_func_t is in use because of the lack
- * to detect EOF (truncated reads).
- */
-#define CAIRO_JPEG_IO_BLOCK_SIZE 1
-/*! In case of original cairo_read_func_t is used fstat() should be used for
- * performance reasons (see CAIRO_JPEG_USE_FSTAT above).
- */
-#define CAIRO_JPEG_USE_FSTAT
-#endif
-
-/*! Define this to test jpeg creation with non-image surfaces. This is only for
- * testing and is to be used together with CAIRO_JPEG_MAIN.
- */
-#undef CAIRO_JPEG_TEST_SIMILAR
-#if defined(CAIRO_JPEG_TEST_SIMILAR) && defined(CAIRO_JPEG_MAIN)
-#include <cairo-pdf.h>
-#endif
-
-#ifndef LIBJPEG_TURBO_VERSION
-/*! This function makes a covnersion for "odd" pixel sizes which typically is a
- * conversion from a 3-byte to a 4-byte (or more) pixel size or vice versa.
- * The conversion is done from the source buffer src to the destination buffer
- * dst. The caller MUST ensure that src and dst have the correct memory size.
- * This is dw * num for dst and sw * num for src. src and dst may point to the
- * same memory address.
- * @param dst Pointer to destination buffer.
- * @param dw Pixel width (in bytes) of pixels in destination buffer, dw >= 3.
- * @param src Pointer to source buffer.
- * @param sw Pixel width (in bytes) of pixels in source buffer, sw >= 3.
- * @param num Number of pixels to convert, num >= 1;
- */
-static void pix_conv(unsigned char *dst, int dw, const unsigned char *src, int sw, int num)
-{
- int si, di;
-
- // safety check
- if (dw < 3 || sw < 3 || dst == NULL || src == NULL)
- return;
-
- num--;
- for (si = num * sw, di = num * dw; si >= 0; si -= sw, di -= dw) {
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- dst[di + 2] = src[si];
- dst[di + 1] = src[si + 1];
- dst[di + 0] = src[si + 2];
-#else
- // FIXME: This is untested, it may be wrong.
- dst[di - 3] = src[si - 3];
- dst[di - 2] = src[si - 2];
- dst[di - 1] = src[si - 1];
-#endif
- }
-}
-#endif
-
-/*! This function creates a JPEG file in memory from a Cairo image surface.
- * @param sfc Pointer to a Cairo surface. It should be an image surface of
- * either CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24. Other formats are
- * converted to CAIRO_FORMAT_RGB24 before compression.
- * Please note that this may give unexpected results because JPEG does not
- * support transparency. Thus, default background color is used to replace
- * transparent regions. The default background color is black if not specified
- * explicitly. Thus converting e.g. PDF surfaces without having any specific
- * background color set will apear with black background and not white as you
- * might expect. In such cases it is suggested to manually convert the surface
- * to RGB24 before calling this function.
- * @param data Pointer to a memory pointer. This parameter receives a pointer
- * to the memory area where the final JPEG data is found in memory. This
- * function reserves the memory properly and it has to be freed by the caller
- * with free(3).
- * @param len Pointer to a variable of type size_t which will receive the final
- * lenght of the memory buffer.
- * @param quality Compression quality, 0-100.
- * @return On success the function returns CAIRO_STATUS_SUCCESS. In case of
- * error CAIRO_STATUS_INVALID_FORMAT is returned.
- */
-cairo_status_t cairo_image_surface_write_to_jpeg_mem(cairo_surface_t *sfc, unsigned char **data,
- size_t *len, int quality)
-{
- struct jpeg_compress_struct cinfo;
- struct jpeg_error_mgr jerr;
- JSAMPROW row_pointer[1];
- cairo_surface_t *other = NULL;
-
- // check valid input format (must be IMAGE_SURFACE && (ARGB32 || RGB24))
- if (cairo_surface_get_type(sfc) != CAIRO_SURFACE_TYPE_IMAGE ||
- (cairo_image_surface_get_format(sfc) != CAIRO_FORMAT_ARGB32 &&
- cairo_image_surface_get_format(sfc) != CAIRO_FORMAT_RGB24)) {
- // create a similar surface with a proper format if supplied input format
- // does not fulfill the requirements
- double x1, y1, x2, y2;
- other = sfc;
- cairo_t *ctx = cairo_create(other);
- // get extents of original surface
- cairo_clip_extents(ctx, &x1, &y1, &x2, &y2);
- cairo_destroy(ctx);
-
- // create new image surface
- sfc = cairo_surface_create_similar_image(other, CAIRO_FORMAT_RGB24, x2 - x1,
- y2 - y1);
- if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS)
- return CAIRO_STATUS_INVALID_FORMAT;
-
- // paint original surface to new surface
- ctx = cairo_create(sfc);
- cairo_set_source_surface(ctx, other, 0, 0);
- cairo_paint(ctx);
- cairo_destroy(ctx);
- }
-
- // finish queued drawing operations
- cairo_surface_flush(sfc);
-
- // init jpeg compression structures
- cinfo.err = jpeg_std_error(&jerr);
- jpeg_create_compress(&cinfo);
-
- // set compression parameters
- jpeg_mem_dest(&cinfo, data, len);
- cinfo.image_width = cairo_image_surface_get_width(sfc);
- cinfo.image_height = cairo_image_surface_get_height(sfc);
-#ifdef LIBJPEG_TURBO_VERSION
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- //cinfo.in_color_space = JCS_EXT_BGRX;
- cinfo.in_color_space = cairo_image_surface_get_format(sfc) == CAIRO_FORMAT_ARGB32 ?
- JCS_EXT_BGRA :
- JCS_EXT_BGRX;
-#else
- //cinfo.in_color_space = JCS_EXT_XRGB;
- cinfo.in_color_space = cairo_image_surface_get_format(sfc) == CAIRO_FORMAT_ARGB32 ?
- JCS_EXT_ARGB :
- JCS_EXT_XRGB;
-#endif
- cinfo.input_components = 4;
-#else
- cinfo.in_color_space = JCS_RGB;
- cinfo.input_components = 3;
-#endif
- jpeg_set_defaults(&cinfo);
- jpeg_set_quality(&cinfo, quality, TRUE);
-
- // start compressor
- jpeg_start_compress(&cinfo, TRUE);
-
- // loop over all lines and compress
- while (cinfo.next_scanline < cinfo.image_height) {
-#ifdef LIBJPEG_TURBO_VERSION
- row_pointer[0] = cairo_image_surface_get_data(sfc) +
- (cinfo.next_scanline * cairo_image_surface_get_stride(sfc));
-#else
- unsigned char row_buf[3 * cinfo.image_width];
- pix_conv(row_buf, 3,
- cairo_image_surface_get_data(sfc) +
- (cinfo.next_scanline * cairo_image_surface_get_stride(sfc)),
- 4, cinfo.image_width);
- row_pointer[0] = row_buf;
-#endif
- (void)jpeg_write_scanlines(&cinfo, row_pointer, 1);
- }
-
- // finalize and close everything
- jpeg_finish_compress(&cinfo);
- jpeg_destroy_compress(&cinfo);
-
- // destroy temporary image surface (if available)
- if (other != NULL)
- cairo_surface_destroy(sfc);
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-/*! This is the internal write function which is called by
- * cairo_image_surface_write_to_jpeg(). It is not exported.
- */
-static cairo_status_t cj_write(void *closure, const unsigned char *data, unsigned int length)
-{
- return write((intptr_t)closure, data, length) < length ? CAIRO_STATUS_WRITE_ERROR :
- CAIRO_STATUS_SUCCESS;
-}
-
-/*! This function writes JPEG file data from a Cairo image surface by using the
- * user-supplied stream writer function write_func().
- * @param sfc Pointer to a Cairo *image* surface. Its format must either be
- * CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24. Other formats are not supported
- * by this function, yet.
- * @param write_func Function pointer to a function which is actually writing
- * the data.
- * @param closure Pointer to user-supplied variable which is directly passed to
- * write_func().
- * @param quality Compression quality, 0-100.
- * @return This function calles cairo_image_surface_write_to_jpeg_mem() and
- * returns its return value.
- */
-cairo_status_t cairo_image_surface_write_to_jpeg_stream(cairo_surface_t *sfc,
- cairo_write_func_t write_func,
- void *closure, int quality)
-{
- cairo_status_t e;
- unsigned char *data = NULL;
- size_t len = 0;
-
- // create JPEG data in memory from surface
- if ((e = cairo_image_surface_write_to_jpeg_mem(sfc, &data, &len, quality)) !=
- CAIRO_STATUS_SUCCESS)
- return e;
-
- // write whole memory block with stream function
- e = write_func(closure, data, len);
-
- // free JPEG memory again and return the return value
- free(data);
- return e;
-}
-
-/*! This function creates a JPEG file from a Cairo image surface.
- * @param sfc Pointer to a Cairo *image* surface. Its format must either be
- * CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24. Other formats are not supported
- * by this function, yet.
- * @param filename Pointer to the filename.
- * @param quality Compression quality, 0-100.
- * @return In case of success CAIRO_STATUS_SUCCESS is returned. If an error
- * occured while opening/creating the file CAIRO_STATUS_DEVICE_ERROR is
- * returned. The error can be tracked down by inspecting errno(3). The function
- * internally calles cairo_image_surface_write_to_jpeg_stream() and returnes
- * its return value respectively (see there).
- */
-cairo_status_t cairo_image_surface_write_to_jpeg(cairo_surface_t *sfc, const char *filename,
- int quality)
-{
- cairo_status_t e;
- int outfile;
-
- // Open/create new file
- if ((outfile = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)) ==
- -1)
- return CAIRO_STATUS_DEVICE_ERROR;
-
- // write surface to file
- e = cairo_image_surface_write_to_jpeg_stream(sfc, cj_write, (void *)(intptr_t)outfile,
- quality);
-
- // close file again and return
- close(outfile);
- return e;
-}
-
-/*! This function decompresses a JPEG image from a memory buffer and creates a
- * Cairo image surface.
- * @param data Pointer to JPEG data (i.e. the full contents of a JPEG file read
- * into this buffer).
- * @param len Length of buffer in bytes.
- * @return Returns a pointer to a cairo_surface_t structure. It should be
- * checked with cairo_surface_status() for errors.
- */
-cairo_surface_t *cairo_image_surface_create_from_jpeg_mem(void *data, size_t len)
-{
- struct jpeg_decompress_struct cinfo;
- struct jpeg_error_mgr jerr;
- JSAMPROW row_pointer[1];
- cairo_surface_t *sfc;
-
- // initialize jpeg decompression structures
- cinfo.err = jpeg_std_error(&jerr);
- jpeg_create_decompress(&cinfo);
- jpeg_mem_src(&cinfo, data, len);
- (void)jpeg_read_header(&cinfo, TRUE);
-
-#ifdef LIBJPEG_TURBO_VERSION
-#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
- cinfo.out_color_space = JCS_EXT_BGRA;
-#else
- cinfo.out_color_space = JCS_EXT_ARGB;
-#endif
-#else
- cinfo.out_color_space = JCS_RGB;
-#endif
-
- // start decompressor
- (void)jpeg_start_decompress(&cinfo);
-
- // create Cairo image surface
- sfc = cairo_image_surface_create(CAIRO_FORMAT_RGB24, cinfo.output_width,
- cinfo.output_height);
- if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) {
- jpeg_destroy_decompress(&cinfo);
- return sfc;
- }
-
- // loop over all scanlines and fill Cairo image surface
- while (cinfo.output_scanline < cinfo.output_height) {
- unsigned char *row_address =
- cairo_image_surface_get_data(sfc) +
- (cinfo.output_scanline * cairo_image_surface_get_stride(sfc));
- row_pointer[0] = row_address;
- (void)jpeg_read_scanlines(&cinfo, row_pointer, 1);
-#ifndef LIBJPEG_TURBO_VERSION
- pix_conv(row_address, 4, row_address, 3, cinfo.output_width);
-#endif
- }
-
- // finish and close everything
- cairo_surface_mark_dirty(sfc);
- (void)jpeg_finish_decompress(&cinfo);
- jpeg_destroy_decompress(&cinfo);
-
- // set jpeg mime data
- cairo_surface_set_mime_data(sfc, CAIRO_MIME_TYPE_JPEG, data, len, free, data);
-
- return sfc;
-}
-
-/*! This function reads a JPEG image from a stream and creates a Cairo image
- * surface.
- * @param read_func Pointer to function which reads data.
- * @param closure Pointer which is passed to read_func().
- * @return Returns a pointer to a cairo_surface_t structure. It should be
- * checked with cairo_surface_status() for errors.
- * @note If the surface returned is invalid you can use errno(3) to determine
- * further reasons. Errno is set according to realloc(3). If you
- * intend to check errno you shall set it to 0 before calling this function
- * because it modifies errno only in case of an error.
- */
-#ifdef USE_CAIRO_READ_FUNC_LEN_T
-cairo_surface_t *cairo_image_surface_create_from_jpeg_stream(cairo_read_func_len_t read_func,
- void *closure)
-#else
-cairo_surface_t *cairo_image_surface_create_from_jpeg_stream(cairo_read_func_t read_func,
- void *closure)
-#endif
-{
- cairo_surface_t *sfc;
- void *data, *tmp;
- ssize_t len, rlen;
- int eof = 0;
-
- // read all data into memory buffer in blocks of CAIRO_JPEG_IO_BLOCK_SIZE
- for (len = 0, data = NULL; !eof; len += rlen) {
- // grow memory buffer and check for error
- if ((tmp = realloc(data, len + CAIRO_JPEG_IO_BLOCK_SIZE)) == NULL)
- break;
- data = tmp;
-
- // read bytes into buffer and check for error
- rlen = read_func(closure, data + len, CAIRO_JPEG_IO_BLOCK_SIZE);
-#ifdef USE_CAIRO_READ_FUNC_LEN_T
- // check for error
- if (rlen == -1)
- break;
-
- // check if EOF occured
- if (rlen < CAIRO_JPEG_IO_BLOCK_SIZE)
- eof++;
-#else
- // check for error
- if (rlen == CAIRO_STATUS_READ_ERROR)
- eof++;
-#endif
- }
-
- // check for error in read loop
- if (!eof) {
- free(data);
- return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0);
- }
-
- // call jpeg decompression and return surface
- sfc = cairo_image_surface_create_from_jpeg_mem(data, len);
- if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS)
- free(data);
-
- return sfc;
-}
-
-#ifdef CAIRO_JPEG_USE_FSTAT
-/*! This function reads an JPEG image from a file an creates a Cairo image
- * surface. Internally the filesize is determined with fstat(2) and then the
- * whole data is read at once.
- * @param filename Pointer to filename of JPEG file.
- * @return Returns a pointer to a cairo_surface_t structure. It should be
- * checked with cairo_surface_status() for errors.
- * @note If the returned surface is invalid you can use errno to determine
- * further reasons. Errno is set according to fopen(3) and malloc(3). If you
- * intend to check errno you shall set it to 0 before calling this function
- * because it does not modify errno itself.
- */
-cairo_surface_t *cairo_image_surface_create_from_jpeg(const char *filename)
-{
- void *data;
- int infile;
- struct stat stat;
-
- // open input file
- if ((infile = open(filename, O_RDONLY)) == -1)
- return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0);
-
- // get stat structure for file size
- if (fstat(infile, &stat) == -1)
- return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0);
-
- // allocate memory
- if ((data = malloc(stat.st_size)) == NULL)
- return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0);
-
- // read data
- if (read(infile, data, stat.st_size) < stat.st_size)
- return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0);
-
- close(infile);
-
- return cairo_image_surface_create_from_jpeg_mem(data, stat.st_size);
-}
-
-#else
-
-/*! This is the read function which is called by
- * cairo_image_surface_create_from_jpeg_stream() (non-fstat-version below). It
- * is not exported.
- */
-#ifdef USE_CAIRO_READ_FUNC_LEN_T
-static ssize_t cj_read(void *closure, unsigned char *data, unsigned int length)
-{
- return read((intptr_t)closure, data, length);
-}
-#else
-static cairo_status_t cj_read(void *closure, unsigned char *data, unsigned int length)
-{
- return read((intptr_t)closure, data, length) < length ? CAIRO_STATUS_READ_ERROR :
- CAIRO_STATUS_SUCCESS;
-}
-#endif
-
-/*! This function reads an JPEG image from a file an creates a Cairo image
- * surface. Internally the function calls
- * cairo_image_surface_create_from_jpeg_stream() to actually read the data.
- * @param filename Pointer to filename of JPEG file.
- * @return Returns a pointer to a cairo_surface_t structure. It should be
- * checked with cairo_surface_status() for errors.
- * @note If the returned surface is invalid you can use errno to determine
- * further reasons. Errno is set according to fopen(3) and malloc(3). If you
- * intend to check errno you shall set it to 0 before calling this function
- * because it does not modify errno itself.
- */
-cairo_surface_t *cairo_image_surface_create_from_jpeg(const char *filename)
-{
- cairo_surface_t *sfc;
- int infile;
-
- // open input file
- if ((infile = open(filename, O_RDONLY)) == -1)
- return cairo_image_surface_create(CAIRO_FORMAT_INVALID, 0, 0);
-
- // call stream loading function
- sfc = cairo_image_surface_create_from_jpeg_stream(cj_read, (void *)(intptr_t)infile);
- close(infile);
-
- return sfc;
-}
-
-#endif
-
-#ifdef CAIRO_JPEG_MAIN
-#include <string.h>
-#include <strings.h>
-
-int strrcasecmp(const char *s1, const char *s2)
-{
- int off = (int)strlen(s1) -
- (int)strlen(s2); // typecast size_t to int because size_t typically is unsigned
- return strcasecmp(s1 + (off < 0 ? 0 : off), s2);
-}
-
-/*! Main routine, only for testing. #undef CAIRO_JPEG_MAIN or simply delete
- * this part if you link this file to your own program.
- */
-int main(int argc, char **argv)
-{
- cairo_surface_t *sfc;
-
-#ifndef CAIRO_JPEG_TEST_SIMILAR
- if (argc < 3) {
- fprintf(stderr, "usage: %s <infile> <outfile>\n", argv[0]);
- return 1;
- }
-
- // test input file type and read file
- if (!strrcasecmp(argv[1], ".png")) {
- // read PNG file
- sfc = cairo_image_surface_create_from_png(argv[1]);
- } else if (!strrcasecmp(argv[1], ".jpg")) {
- // read JPEG file
- sfc = cairo_image_surface_create_from_jpeg(argv[1]);
- } else {
- fprintf(stderr, "source file is neither JPG nor PNG\n");
- return 1;
- }
-
- // check surface status
- if (cairo_surface_status(sfc) != CAIRO_STATUS_SUCCESS) {
- fprintf(stderr, "error loading image: %s",
- cairo_status_to_string(cairo_surface_status(sfc)));
- return 2;
- }
-
- // test output file type and write file
- if (!strrcasecmp(argv[2], ".png")) {
- // write PNG file
- cairo_surface_write_to_png(sfc, argv[2]);
- } else if (!strrcasecmp(argv[2], ".jpg")) {
- // write JPEG file
- cairo_image_surface_write_to_jpeg(sfc, argv[2], 90);
- } else {
- fprintf(stderr, "destination file is neither JPG nor PNG\n");
- return 1;
- }
-
- cairo_surface_destroy(sfc);
-
-#else
- sfc = cairo_pdf_surface_create("xyz.pdf", 595.276, 841.890);
-
- cairo_t *ctx = cairo_create(sfc);
- cairo_set_source_rgb(ctx, 1, 1, 1);
- cairo_paint(ctx);
- cairo_move_to(ctx, 100, 100);
- cairo_set_source_rgb(ctx, 1, 0, 0);
- cairo_set_line_width(ctx, 3);
- cairo_line_to(ctx, 400, 400);
- cairo_stroke(ctx);
- cairo_destroy(ctx);
-
- cairo_image_surface_write_to_jpeg(sfc, "xyz.jpg", 90);
- cairo_surface_destroy(sfc);
-#endif
-
- return 0;
-}
-
-#endif
diff --git a/zathura-note/cairo_jpg.h b/zathura-note/cairo_jpg.h
deleted file mode 100644
index 5467581..0000000
--- a/zathura-note/cairo_jpg.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Copyright 2018 Bernhard R. Fischer, 4096R/8E24F29D <bf@abenteuerland.at>
- *
- * This file is part of Cairo_JPG.
- *
- * Cairo_JPG is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Cairo_JPG is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Cairo_JPG. If not, see <https://www.gnu.org/licenses/>.
- */
-
-#ifndef CAIRO_JPEG_H
-#define CAIRO_JPEG_H
-
-/*! \file cairo_jpg.h
- * This file contains all prototypes for the Cairo-JPEG functions implemented
- * in cairo_jpg.c. See there for the function documentation.
- *
- * @author Bernhard R. Fischer, 4096R/8E24F29D <bf@abenteuerland.at>
- * @version 2018/12/11
- * @license LGPL3
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <cairo.h>
-#include <stddef.h>
-
-#ifdef USE_CAIRO_READ_FUNC_LEN_T
-/*! This is the type for the stream read function. Which must be implemented by
- * the user if cairo_image_surface_create_from_jpeg_stream() is used. Please
- * note that this prototype is slightly different from cairo_read_func_t which
- * is used by cairo_image_surface_create_from_png_stream().
- * This new prototype is defined because the original prototype
- * cairo_read_func_t does not allow to detect truncated reads. This issue was
- * discussed on the cairographics mailinglist, see
- * https://lists.cairographics.org/archives/cairo/2016-March/027298.html
- * @param closure This parameter is directly passed through by
- * cairo_image_surface_create_from_jpeg_stream().
- * @param data Pointer to data buffer which will receive the data.
- * @param length Size of the data buffer in bytes.
- * @return This function must return the actually length that was read into the
- * buffer. This may actually be less than length which indicates an EOF. In
- * case of any fatal unrecoverable error on the input stream -1 shall be
- * returned.
- */
-typedef ssize_t (*cairo_read_func_len_t)(void *closure, unsigned char *data, unsigned int length);
-#endif
-
-cairo_status_t cairo_image_surface_write_to_jpeg_mem(cairo_surface_t *sfc, unsigned char **data,
- size_t *len, int quality);
-cairo_status_t cairo_image_surface_write_to_jpeg_stream(cairo_surface_t *sfc,
- cairo_write_func_t write_func,
- void *closure, int quality);
-cairo_status_t cairo_image_surface_write_to_jpeg(cairo_surface_t *sfc, const char *filename,
- int quality);
-cairo_surface_t *cairo_image_surface_create_from_jpeg_mem(void *data, size_t len);
-#ifdef USE_CAIRO_READ_FUNC_LEN_T
-cairo_surface_t *cairo_image_surface_create_from_jpeg_stream(cairo_read_func_len_t read_func,
- void *closure);
-#else
-cairo_surface_t *cairo_image_surface_create_from_jpeg_stream(cairo_read_func_t read_func,
- void *closure);
-#endif
-cairo_surface_t *cairo_image_surface_create_from_jpeg(const char *filename);
-
-#endif
diff --git a/zathura-note/note.c b/zathura-note/note.c
index 282e17b..8666af8 100644
--- a/zathura-note/note.c
+++ b/zathura-note/note.c
@@ -1,13 +1,14 @@
// Copyright (c) 2021 Marvin Borner
// WTFPL License (only for note.*)
-#include "cairo_jpg.h"
#include "plugin.h"
#include <plist/plist.h>
#include <stdio.h>
#include <zip.h>
+#include <jpeglib.h>
+
// Data struct for entire document
typedef struct {
zip_t *zip;
@@ -27,6 +28,10 @@ typedef struct {
#define SESSION_OBJECTS_GENERAL_INFO 1
#define SESSION_OBJECTS_LAYOUT_INFO 2
+/**
+ * Zip wrappers/utilities
+ */
+
static void zip_load(zip_t *zip, const char *root_name, const char *path, void **buf,
size_t *length)
{
@@ -54,6 +59,10 @@ static void zip_load(zip_t *zip, const char *root_name, const char *path, void *
}
}
+/**
+ * Plist wrappers/utilities
+ */
+
// For debugging/reverse engineering
#define INDENT 4
static void plist_dump(plist_t plist, int depth)
@@ -329,6 +338,98 @@ static float plist_page_width(plist_t objects)
return val;
}
+/**
+ * Cairo wrappers/utilities
+ */
+
+typedef struct {
+ char *data;
+ size_t length;
+} cairo_read_closure;
+
+// Cairo is weird. Why can't we just pass a data buffer directly?
+static cairo_status_t cairo_read(void *data, unsigned char *buf, unsigned int length)
+{
+ cairo_read_closure *closure = data;
+
+ if (length > closure->length)
+ return CAIRO_STATUS_READ_ERROR;
+
+ memcpy(buf, closure->data, length);
+
+ closure->length -= length;
+ closure->data += length;
+
+ return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_surface_t *cairo_surface_scale(cairo_surface_t *surface, float width, float height)
+{
+ int unscaled_width = cairo_image_surface_get_width(surface);
+ int unscaled_height = cairo_image_surface_get_height(surface);
+ cairo_surface_t *result = cairo_surface_create_similar(
+ surface, cairo_surface_get_content(surface), width, height);
+ cairo_t *cairo = cairo_create(result);
+ cairo_scale(cairo, width / (float)unscaled_width, height / (float)unscaled_height);
+ cairo_set_source_surface(cairo, surface, 0, 0);
+ cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(cairo);
+ cairo_destroy(cairo);
+ return result;
+}
+
+cairo_surface_t *cairo_image_surface_create_from_jpeg_mem(void *data, size_t len)
+{
+ struct jpeg_decompress_struct jpeg;
+ struct jpeg_error_mgr jpeg_err;
+ jpeg.err = jpeg_std_error(&jpeg_err);
+ jpeg_create_decompress(&jpeg);
+ jpeg_mem_src(&jpeg, data, len);
+ jpeg_read_header(&jpeg, TRUE);
+
+#ifdef LIBJPEG_TURBO_VERSION
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+ jpeg.out_color_space = JCS_EXT_BGRA;
+#else
+ jpeg.out_color_space = JCS_EXT_ARGB;
+#endif
+#else
+ jpeg.out_color_space = JCS_RGB;
+#endif
+
+ jpeg_start_decompress(&jpeg);
+
+ cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, jpeg.output_width,
+ jpeg.output_height);
+ if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
+ jpeg_destroy_decompress(&jpeg);
+ return surface;
+ }
+
+ while (jpeg.output_scanline < jpeg.output_height) {
+ unsigned char *row_address =
+ cairo_image_surface_get_data(surface) +
+ (jpeg.output_scanline * cairo_image_surface_get_stride(surface));
+ JSAMPROW row_pointer = row_address;
+ jpeg_read_scanlines(&jpeg, &row_pointer, 1);
+#ifndef LIBJPEG_TURBO_VERSION
+ pix_conv(row_address, 4, row_address, 3, jpeg.output_width);
+#endif
+ }
+
+ cairo_surface_mark_dirty(surface);
+ jpeg_finish_decompress(&jpeg);
+ jpeg_destroy_decompress(&jpeg);
+
+ cairo_surface_set_mime_data(surface, CAIRO_MIME_TYPE_JPEG, data, len, free, data);
+
+ return surface;
+}
+
+/**
+ * Main zathura plugin implementations
+ */
+
GIRARA_HIDDEN zathura_error_t note_document_open(zathura_document_t *document)
{
zathura_error_t error = ZATHURA_ERROR_OK;
@@ -434,42 +535,6 @@ GIRARA_HIDDEN zathura_error_t note_page_clear(zathura_page_t *page, void *data)
return ZATHURA_ERROR_OK;
}
-typedef struct {
- char *data;
- size_t length;
-} cairo_read_closure;
-
-// Cairo is weird. Why can't we just pass a data buffer directly (like with cairo_jpg)?!
-static cairo_status_t cairo_read(void *data, unsigned char *buf, unsigned int length)
-{
- cairo_read_closure *closure = data;
-
- if (length > closure->length)
- return CAIRO_STATUS_READ_ERROR;
-
- memcpy(buf, closure->data, length);
-
- closure->length -= length;
- closure->data += length;
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_surface_t *cairo_surface_scale(cairo_surface_t *surface, float width, float height)
-{
- int unscaled_width = cairo_image_surface_get_width(surface);
- int unscaled_height = cairo_image_surface_get_height(surface);
- cairo_surface_t *result = cairo_surface_create_similar(
- surface, cairo_surface_get_content(surface), width, height);
- cairo_t *cairo = cairo_create(result);
- cairo_scale(cairo, width / (float)unscaled_width, height / (float)unscaled_height);
- cairo_set_source_surface(cairo, surface, 0, 0);
- cairo_set_operator(cairo, CAIRO_OPERATOR_SOURCE);
- cairo_paint(cairo);
- cairo_destroy(cairo);
- return result;
-}
-
static void note_page_render_image_object(note_page_t *page, plist_t objects, int index)
{
char missing = 0;