@@ -1,6 +1,6 @@ | |||||
all: sxiv | all: sxiv | ||||
VERSION=git-20110127 | VERSION=git-20110128 | ||||
CC?=gcc | CC?=gcc | ||||
PREFIX?=/usr/local | PREFIX?=/usr/local | ||||
@@ -30,8 +30,16 @@ Usage | |||||
----- | ----- | ||||
sxiv supports the following command-line options: | sxiv supports the following command-line options: | ||||
-w WIDTHxHEIGHT set window width to WIDTH and height to HEIGHT | -d scale all images to 100%, but fit large images into window | ||||
(if HEIGHT is omitted, height is also set to WIDTH) | -f start in fullscreen mode | ||||
-p pixelize, i.e. turn off image anti-aliasing | |||||
-s scale all images to fit into window | |||||
-v print version information and exit | |||||
-w WIDTHxHEIGHT | |||||
set window width to WIDTH and height to HEIGHT | |||||
(if HEIGHT is omitted, height is also set to WIDTH) | |||||
-Z same as `-z 100' | |||||
-z ZOOM scale all images to current zoom level, use ZOOM at startup | |||||
Use the following keys to control sxiv: | Use the following keys to control sxiv: | ||||
@@ -1,4 +1,5 @@ | |||||
/* default window dimensions: */ | /* default window dimensions: * | ||||
* (also controllable via -w option) */ | |||||
#define WIN_WIDTH 800 | #define WIN_WIDTH 800 | ||||
#define WIN_HEIGHT 600 | #define WIN_HEIGHT 600 | ||||
@@ -7,6 +8,7 @@ | |||||
#define BG_COLOR "#888888" | #define BG_COLOR "#888888" | ||||
/* how should images be scaled when they are loaded?: * | /* how should images be scaled when they are loaded?: * | ||||
* (also controllable via -d/-s/-Z/-z options) * | |||||
* SCALE_DOWN: 100%, but fit large images into window, * | * SCALE_DOWN: 100%, but fit large images into window, * | ||||
* SCALE_FIT: fit all images into window, * | * SCALE_FIT: fit all images into window, * | ||||
* SCALE_ZOOM: use current zoom level, 100% at startup */ | * SCALE_ZOOM: use current zoom level, 100% at startup */ | ||||
@@ -23,6 +23,7 @@ | |||||
#include "sxiv.h" | #include "sxiv.h" | ||||
#include "image.h" | #include "image.h" | ||||
#include "options.h" | |||||
int zl_cnt; | int zl_cnt; | ||||
float zoom_min; | float zoom_min; | ||||
@@ -34,8 +35,10 @@ void img_init(img_t *img, win_t *win) { | |||||
zoom_max = zoom_levels[zl_cnt - 1] / 100.0; | zoom_max = zoom_levels[zl_cnt - 1] / 100.0; | ||||
if (img) { | if (img) { | ||||
img->zoom = 1.0; | img->zoom = options->zoom; | ||||
img->aa = 1; | img->zoom = MAX(img->zoom, zoom_min); | ||||
img->zoom = MIN(img->zoom, zoom_max); | |||||
img->aa = options->aa; | |||||
} | } | ||||
if (win) { | if (win) { | ||||
@@ -102,32 +105,20 @@ void img_check_pan(img_t *img, win_t *win) { | |||||
void img_render(img_t *img, win_t *win) { | void img_render(img_t *img, win_t *win) { | ||||
int sx, sy, sw, sh; | int sx, sy, sw, sh; | ||||
int dx, dy, dw, dh; | int dx, dy, dw, dh; | ||||
float zw, zh; | |||||
if (!img || !win || !imlib_context_get_image()) | if (!img || !win || !imlib_context_get_image()) | ||||
return; | return; | ||||
if (!img->zoomed && SCALE_MODE != SCALE_ZOOM) { | if (!img->zoomed && options->scalemode != SCALE_ZOOM) { | ||||
/* set zoom level to fit image into window */ | img_fit(img, win); | ||||
zw = (float) win->w / (float) img->w; | if (options->scalemode == SCALE_DOWN && img->zoom > 1.0) | ||||
zh = (float) win->h / (float) img->h; | |||||
img->zoom = MIN(zw, zh); | |||||
if (img->zoom < zoom_min) | |||||
img->zoom = zoom_min; | |||||
else if (img->zoom > zoom_max) | |||||
img->zoom = zoom_max; | |||||
if (SCALE_MODE == SCALE_DOWN && img->zoom > 1.0) | |||||
img->zoom = 1.0; | img->zoom = 1.0; | ||||
} | } | ||||
if (!img->re) { | if (!img->re) { | ||||
/* rendered for the first time */ | /* rendered for the first time */ | ||||
img->re = 1; | img->re = 1; | ||||
/* center image in window */ | img_center(img, win); | ||||
img->x = (win->w - img->w * img->zoom) / 2; | |||||
img->y = (win->h - img->h * img->zoom) / 2; | |||||
} | } | ||||
if (img->checkpan) { | if (img->checkpan) { | ||||
@@ -167,14 +158,37 @@ void img_render(img_t *img, win_t *win) { | |||||
win_draw(win); | win_draw(win); | ||||
} | } | ||||
int img_fit(img_t *img, win_t *win) { | |||||
float oz, zw, zh; | |||||
if (!img || !win) | |||||
return 0; | |||||
oz = img->zoom; | |||||
zw = (float) win->w / (float) img->w; | |||||
zh = (float) win->h / (float) img->h; | |||||
img->zoom = MIN(zw, zh); | |||||
img->zoom = MAX(img->zoom, zoom_min); | |||||
img->zoom = MIN(img->zoom, zoom_max); | |||||
return oz != img->zoom; | |||||
} | |||||
void img_center(img_t *img, win_t *win) { | |||||
if (!img || !win) | |||||
return; | |||||
img->x = (win->w - img->w * img->zoom) / 2; | |||||
img->y = (win->h - img->h * img->zoom) / 2; | |||||
} | |||||
int img_zoom(img_t *img, float z) { | int img_zoom(img_t *img, float z) { | ||||
if (!img) | if (!img) | ||||
return 0; | return 0; | ||||
if (z < zoom_min) | z = MAX(z, zoom_min); | ||||
z = zoom_min; | z = MIN(z, zoom_max); | ||||
else if (z > zoom_max) | |||||
z = zoom_max; | |||||
if (z != img->zoom) { | if (z != img->zoom) { | ||||
img->x -= (img->w * z - img->w * img->zoom) / 2; | img->x -= (img->w * z - img->w * img->zoom) / 2; | ||||
@@ -21,11 +21,11 @@ | |||||
#include "window.h" | #include "window.h" | ||||
enum scalemode { | typedef enum scalemode_e { | ||||
SCALE_DOWN = 0, | SCALE_DOWN = 0, | ||||
SCALE_FIT, | SCALE_FIT, | ||||
SCALE_ZOOM | SCALE_ZOOM | ||||
}; | } scalemode_t; | ||||
typedef enum pandir_e { | typedef enum pandir_e { | ||||
PAN_LEFT = 0, | PAN_LEFT = 0, | ||||
@@ -52,6 +52,9 @@ void img_free(img_t*); | |||||
int img_load(img_t*, const char*); | int img_load(img_t*, const char*); | ||||
void img_render(img_t*, win_t*); | void img_render(img_t*, win_t*); | ||||
int img_fit(img_t*, win_t*); | |||||
void img_center(img_t*, win_t*); | |||||
int img_zoom_in(img_t*); | int img_zoom_in(img_t*); | ||||
int img_zoom_out(img_t*); | int img_zoom_out(img_t*); | ||||
@@ -29,7 +29,7 @@ options_t _options; | |||||
const options_t *options = (const options_t*) &_options; | const options_t *options = (const options_t*) &_options; | ||||
void print_usage() { | void print_usage() { | ||||
printf("usage: sxiv [-hv] [-w WIDTH[xHEIGHT]] FILES...\n"); | printf("usage: sxiv [-dfhpsvZ] [-w WIDTH[xHEIGHT]] [-z ZOOM] FILES...\n"); | ||||
} | } | ||||
void print_version() { | void print_version() { | ||||
@@ -39,19 +39,37 @@ void print_version() { | |||||
void parse_options(int argc, char **argv) { | void parse_options(int argc, char **argv) { | ||||
unsigned short w, h; | unsigned short w, h; | ||||
float z; | |||||
int opt; | int opt; | ||||
_options.scalemode = SCALE_MODE; | |||||
_options.zoom = 1.0; | |||||
_options.aa = 1; | |||||
_options.winw = w = 0; | _options.winw = w = 0; | ||||
_options.winh = h = 0; | _options.winh = h = 0; | ||||
_options.fullscreen = 0; | |||||
while ((opt = getopt(argc, argv, "hvw:")) != -1) { | while ((opt = getopt(argc, argv, "dfhpsvw:Zz:")) != -1) { | ||||
switch (opt) { | switch (opt) { | ||||
case '?': | case '?': | ||||
print_usage(); | print_usage(); | ||||
exit(1); | exit(1); | ||||
case 'd': | |||||
_options.scalemode = SCALE_DOWN; | |||||
break; | |||||
case 'f': | |||||
_options.fullscreen = 1; | |||||
break; | |||||
case 'h': | case 'h': | ||||
print_usage(); | print_usage(); | ||||
exit(0); | exit(0); | ||||
case 'p': | |||||
_options.aa = 0; | |||||
break; | |||||
case 's': | |||||
_options.scalemode = SCALE_FIT; | |||||
break; | |||||
case 'v': | case 'v': | ||||
print_version(); | print_version(); | ||||
exit(0); | exit(0); | ||||
@@ -65,6 +83,20 @@ void parse_options(int argc, char **argv) { | |||||
_options.winh = (int) h; | _options.winh = (int) h; | ||||
} | } | ||||
break; | break; | ||||
case 'Z': | |||||
_options.scalemode = SCALE_ZOOM; | |||||
_options.zoom = 1.0; | |||||
break; | |||||
case 'z': | |||||
_options.scalemode = SCALE_ZOOM; | |||||
if (!sscanf(optarg, "%f", &z) || z < 0) { | |||||
fprintf(stderr, "sxiv: invalid argument for option -z: %s\n", | |||||
optarg); | |||||
exit(1); | |||||
} else { | |||||
_options.zoom = z / 100.0; | |||||
} | |||||
break; | |||||
} | } | ||||
} | } | ||||
@@ -19,11 +19,19 @@ | |||||
#ifndef OPTIONS_H | #ifndef OPTIONS_H | ||||
#define OPTIONS_H | #define OPTIONS_H | ||||
#include "image.h" | |||||
typedef struct options_s { | typedef struct options_s { | ||||
const char **filenames; | const char **filenames; | ||||
int filecnt; | int filecnt; | ||||
scalemode_t scalemode; | |||||
float zoom; | |||||
unsigned char aa; | |||||
int winw; | int winw; | ||||
int winh; | int winh; | ||||
unsigned char fullscreen; | |||||
} options_t; | } options_t; | ||||
extern const options_t *options; | extern const options_t *options; | ||||
@@ -3,11 +3,12 @@ | |||||
sxiv \- Simple (or small or suckless) X Image Viewer | sxiv \- Simple (or small or suckless) X Image Viewer | ||||
.SH SYNOPSIS | .SH SYNOPSIS | ||||
.B sxiv | .B sxiv | ||||
.RB [ \-hv ] | .RB [ \-dfhpsvZ ] | ||||
[ | .RB [ \-w | ||||
.B \-w | |||||
.IB WIDTH x HEIGHT | .IB WIDTH x HEIGHT | ||||
] | ] | ||||
.RB [ \-z | |||||
.IR ZOOM ] | |||||
.IR FILE ... | .IR FILE ... | ||||
.SH DESCRIPTION | .SH DESCRIPTION | ||||
sxiv is a simple image viewer for X. It only has the most basic features | sxiv is a simple image viewer for X. It only has the most basic features | ||||
@@ -17,9 +18,21 @@ Please note, that the fullscreen mode requires an EWMH/NetWM compliant window | |||||
manager. | manager. | ||||
.SH OPTIONS | .SH OPTIONS | ||||
.TP | .TP | ||||
.B \-d | |||||
Scale all images to 100%, but fit large images into window. | |||||
.TP | |||||
.B \-f | |||||
Start in fullscreen mode. | |||||
.TP | |||||
.B \-h | .B \-h | ||||
Print brief usage information to standard output and exit. | Print brief usage information to standard output and exit. | ||||
.TP | .TP | ||||
.B \-p | |||||
Pixelize images, i.e. turn off anti-aliasing. | |||||
.TP | |||||
.B \-s | |||||
Scale all images to fit into window. | |||||
.TP | |||||
.B \-v | .B \-v | ||||
Print version information to standard output and exit. | Print version information to standard output and exit. | ||||
.TP | .TP | ||||
@@ -32,6 +45,14 @@ If | |||||
.I HEIGHT | .I HEIGHT | ||||
is omitted, height is also set to | is omitted, height is also set to | ||||
.IR WIDTH . | .IR WIDTH . | ||||
.TP | |||||
.B \-Z | |||||
The same as `-z 100'. | |||||
.TP | |||||
.BI "\-z " ZOOM | |||||
Scale all images to the current zoom level, use a zoom level of | |||||
.I ZOOM | |||||
at startup. | |||||
.SH KEYBOARD COMMANDS | .SH KEYBOARD COMMANDS | ||||
.SS General | .SS General | ||||
.TP | .TP | ||||
@@ -54,6 +54,7 @@ void win_open(win_t *win) { | |||||
win->bgcol = bgcol.pixel; | win->bgcol = bgcol.pixel; | ||||
win->pm = 0; | win->pm = 0; | ||||
win->fullscreen = 0; | |||||
win->w = MIN(options->winw, e->scrw); | win->w = MIN(options->winw, e->scrw); | ||||
win->h = MIN(options->winh, e->scrh); | win->h = MIN(options->winh, e->scrh); | ||||
win->x = (e->scrw - win->w) / 2; | win->x = (e->scrw - win->w) / 2; | ||||
@@ -81,6 +82,9 @@ void win_open(win_t *win) { | |||||
XMapWindow(e->dpy, win->xwin); | XMapWindow(e->dpy, win->xwin); | ||||
XFlush(e->dpy); | XFlush(e->dpy); | ||||
if (options->fullscreen) | |||||
win_toggle_fullscreen(win); | |||||
} | } | ||||
void win_close(win_t *win) { | void win_close(win_t *win) { | ||||
@@ -45,7 +45,7 @@ typedef struct win_s { | |||||
int y; | int y; | ||||
int bw; | int bw; | ||||
int fullscreen; | unsigned char fullscreen; | ||||
} win_t; | } win_t; | ||||
void win_open(win_t*); | void win_open(win_t*); | ||||