Skip to content
This repository has been archived by the owner on Jan 16, 2023. It is now read-only.

added svg support and modified Makefile enough so that it compiles #440

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ HAVE_GIFLIB = 1
# enable features requiring libexif (-lexif)
HAVE_LIBEXIF = 1

cflags = -std=c99 -Wall -pedantic $(CFLAGS)
cflags = -std=c99 -Wall -pedantic $(CFLAGS) `pkg-config --cflags --libs librsvg-2.0 cairo`
cppflags = -I. $(CPPFLAGS) -D_XOPEN_SOURCE=700 \
-DHAVE_GIFLIB=$(HAVE_GIFLIB) -DHAVE_LIBEXIF=$(HAVE_LIBEXIF) \
-I/usr/include/freetype2 -I$(PREFIX)/include/freetype2
Expand All @@ -39,7 +39,7 @@ $(V).SILENT:

sxiv: $(objs)
@echo "LINK $@"
$(CC) $(LDFLAGS) -o $@ $(objs) $(ldlibs)
$(CC) $(LDFLAGS) -o $@ $(objs) $(ldlibs) $(cflags)

$(objs): Makefile sxiv.h commands.lst config.h
options.o: version.h
Expand Down
8 changes: 8 additions & 0 deletions config.def.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ static const bool ANTI_ALIAS = true;
*/
static const bool ALPHA_LAYER = false;

/* fallback height and width for svg documents.
* use these values in case svg document does not specify height and width.
*/
enum {
FB_SVG_HEIGHT = 512,
FB_SVG_WIDTH = 512
};

#endif
#ifdef _THUMBS_CONFIG

Expand Down
99 changes: 93 additions & 6 deletions image.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <sys/types.h>
#include <unistd.h>

#include<cairo.h>

#if HAVE_LIBEXIF
#include <libexif/exif-data.h>
#endif
Expand Down Expand Up @@ -54,6 +56,7 @@ void img_init(img_t *img, win_t *win)
imlib_context_set_colormap(win->env.cmap);

img->im = NULL;
img->svg.h = NULL;
img->win = win;
img->scalemode = options->scalemode;
img->zoom = options->zoom;
Expand Down Expand Up @@ -293,6 +296,64 @@ bool img_load_gif(img_t *img, const fileinfo_t *file)
}
#endif /* HAVE_GIFLIB */

svg_t img_open_svg(const fileinfo_t *file) {
svg_t svg;

svg.h = rsvg_handle_new_from_file(file->name, 0);
svg.viewbox.height = FB_SVG_HEIGHT;
svg.viewbox.width = FB_SVG_WIDTH;

gboolean has_out_viewbox;
gboolean has_out_height;
RsvgLength out_height;
gboolean has_out_width;
RsvgLength out_width;

rsvg_handle_get_intrinsic_dimensions(svg.h,
&has_out_height, &out_height,
&has_out_width, &out_width,
&has_out_viewbox, &svg.viewbox);

if (!has_out_viewbox && has_out_height & has_out_width) {
svg.viewbox.height = out_height.length;
svg.viewbox.width = out_width.length;
}

svg.size = svg.viewbox;

return svg;
}

bool img_load_svg(img_t *img, float z) {
img->svg.viewbox.height = img->svg.size.height * z;
img->svg.viewbox.width = img->svg.size.width * z;

cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
(int) img->svg.viewbox.width,
(int) img->svg.viewbox.height);
cairo_t *cr = cairo_create(surface);

GError *e = NULL;
rsvg_handle_render_document(img->svg.h, cr, &img->svg.viewbox, &e);

DATA32 *svg_buffer;
svg_buffer = (DATA32 *) cairo_image_surface_get_data(surface);

img->im = imlib_create_image_using_copied_data((int) img->svg.viewbox.width, (int) img->svg.viewbox.height, svg_buffer);
if (img->im == NULL)
return false;

imlib_context_set_image(img->im);
imlib_image_set_has_alpha(1);
img->w = img->svg.viewbox.width;
img->h = img->svg.viewbox.height;

cairo_surface_destroy(surface);
cairo_destroy(cr);

return true;
}

Imlib_Image img_open(const fileinfo_t *file)
{
struct stat st;
Expand All @@ -302,6 +363,7 @@ Imlib_Image img_open(const fileinfo_t *file)
stat(file->path, &st) == 0 && S_ISREG(st.st_mode))
{
im = imlib_load_image(file->path);

if (im != NULL) {
imlib_context_set_image(im);
if (imlib_image_get_data_for_reading_only() == NULL) {
Expand All @@ -310,17 +372,22 @@ Imlib_Image img_open(const fileinfo_t *file)
}
}
}
if (im == NULL && (file->flags & FF_WARN))
error(0, 0, "%s: Error opening image", file->name);

return im;
}

bool img_load(img_t *img, const fileinfo_t *file)
{
const char *fmt;

if ((img->im = img_open(file)) == NULL)
return false;
if ((img->im = img_open(file)) == NULL) {
img->svg = img_open_svg(file);
if ((img->svg.h == NULL) || img_load_svg(img, 1.0) == false) {
if (file->flags & FF_WARN)
error(0, 0, "%s: Error opening image", file->name);
return false;
}
}

imlib_image_set_changes_on_disk();

Expand Down Expand Up @@ -361,6 +428,9 @@ CLEANUP void img_close(img_t *img, bool decache)
imlib_free_image();
img->im = NULL;
}

if (img->svg.h)
g_object_unref(img->svg.h);
}

void img_check_pan(img_t *img, bool moved)
Expand All @@ -369,11 +439,17 @@ void img_check_pan(img_t *img, bool moved)
float w, h, ox, oy;

win = img->win;
w = img->w * img->zoom;
h = img->h * img->zoom;
ox = img->x;
oy = img->y;

if (img->svg.h) {
w = img->w;
h = img->h;
} else {
w = img->w * img->zoom;
h = img->h * img->zoom;
}

if (w < win->w)
img->x = (win->w - w) / 2;
else if (img->x > 0)
Expand Down Expand Up @@ -431,6 +507,10 @@ void img_render(img_t *img)
Imlib_Image bg;
unsigned long c;

float z = img->zoom;
if (img->svg.h)
img->zoom = 1.0;

win = img->win;
img_fit(img);

Expand Down Expand Up @@ -510,6 +590,9 @@ void img_render(img_t *img)
imlib_render_image_part_on_drawable_at_size(sx, sy, sw, sh, dx, dy, dw, dh);
}
img->dirty = false;

if (img->svg.h)
img->zoom = z;
}

bool img_fit_win(img_t *img, scalemode_t sm)
Expand Down Expand Up @@ -539,6 +622,10 @@ bool img_zoom(img_t *img, float z)
if (zoomdiff(img, z) != 0) {
int x, y;

if (img->svg.h) {
img_load_svg(img, z);
}

win_cursor_pos(img->win, &x, &y);
if (x < 0 || x >= img->win->w || y < 0 || y >= img->win->h) {
x = img->win->w / 2;
Expand Down
2 changes: 1 addition & 1 deletion sxiv.desktop
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ Type=Application
Name=sxiv
GenericName=Image Viewer
Exec=sxiv %F
MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;image/x-bmp;image/x-portable-anymap;image/x-portable-bitmap;image/x-portable-graymap;image/x-tga;image/x-xpixmap;
MimeType=image/bmp;image/gif;image/jpeg;image/jpg;image/png;image/tiff;image/x-bmp;image/x-portable-anymap;image/x-portable-bitmap;image/x-portable-graymap;image/x-tga;image/x-xpixmap;image/svg+xml;
NoDisplay=true
Icon=sxiv
10 changes: 10 additions & 0 deletions sxiv.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <Imlib2.h>
#include <X11/Xlib.h>

#include <librsvg/rsvg.h>

/*
* Annotation for functions called in cleanup().
* These functions are not allowed to call error(!0, ...) or exit().
Expand Down Expand Up @@ -206,11 +208,19 @@ typedef struct {
int length;
} multi_img_t;

typedef struct {
RsvgHandle *h;
RsvgRectangle size; /* size of the actual docuemnt which will be used while scaling */
RsvgRectangle viewbox; /* size of the scaled image which will be rendered */
} svg_t;

struct img {
Imlib_Image im;
int w;
int h;

svg_t svg;

win_t *win;
float x;
float y;
Expand Down