Skip to content
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
11 changes: 11 additions & 0 deletions include/slurp.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,14 @@

#define TOUCH_ID_EMPTY -1

enum slurp_label_anchor {
ANCHOR_NONE = 0,
ANCHOR_TOP = 1,
ANCHOR_BOTTOM = 2,
ANCHOR_LEFT = 4,
ANCHOR_RIGHT = 8,
};

struct slurp_box {
int32_t x, y;
int32_t width, height;
Expand Down Expand Up @@ -48,6 +56,8 @@ struct slurp_state {
uint32_t border;
uint32_t selection;
uint32_t choice;
uint32_t label_text;
uint32_t label_background;
} colors;

const char *font_family;
Expand All @@ -60,6 +70,7 @@ struct slurp_state {
struct wl_list boxes; // slurp_box::link
bool fixed_aspect_ratio;
double aspect_ratio; // h / w
enum slurp_label_anchor label_anchor;

struct slurp_box result;
};
Expand Down
44 changes: 41 additions & 3 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#define BG_COLOR 0xFFFFFF40
#define BORDER_COLOR 0x000000FF
#define SELECTION_COLOR 0x00000000
#define LABEL_COLOR 0xFFFFFFFF
#define LABEL_BG_COLOR 0x000000FF
#define FONT_FAMILY "sans-serif"

static void noop() {
Expand Down Expand Up @@ -719,13 +721,16 @@ static const char usage[] =
" -c #rrggbbaa Set border color.\n"
" -s #rrggbbaa Set selection color.\n"
" -B #rrggbbaa Set option box color.\n"
" -l #rrggbbaa Set label text color.\n"
" -L #rrggbbaa Set label background color.\n"
" -F s Set the font family for the dimensions.\n"
" -w n Set border weight.\n"
" -f s Set output format.\n"
" -o Select a display output.\n"
" -p Select a single point.\n"
" -r Restrict selection to predefined boxes.\n"
" -a w:h Force aspect ratio.\n";
" -a w:h Force aspect ratio.\n"
" -P Position labels on the option boxes.\n";

uint32_t parse_color(const char *color) {
if (color[0] == '#') {
Expand All @@ -745,6 +750,27 @@ uint32_t parse_color(const char *color) {
return res;
}


enum slurp_label_anchor parse_label_anchor(const char *anchor) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"center-top" is equivalent to "top-center" is equivalent to "center" is equivalent to "top-bottom-left-right-center".

It will also happily accept something like "top-nonsenes" and treat it the same as "top" or "not-top" is also the same as "top", or "neotop".

Should this be more strict in what it accepts?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also "top-bottom" is the same as "center" (and similarly "left-right")

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this lack of strictness simplifies parsing without any harm/conflict.
The structure of the anchor is the same as used for wlr_layer_surface and I just added center as convenience. As such the same duplications happen, but I don't se an issue there.

enum slurp_label_anchor label_anchor = ANCHOR_NONE;
if (strstr(anchor, "top") != NULL) {
label_anchor |= ANCHOR_TOP;
}
if (strstr(anchor, "bottom") != NULL) {
label_anchor |= ANCHOR_BOTTOM;
}
if (strstr(anchor, "left") != NULL) {
label_anchor |= ANCHOR_LEFT;
}
if (strstr(anchor, "right") != NULL) {
label_anchor |= ANCHOR_RIGHT;
}
if (strstr(anchor, "center") != NULL) {
label_anchor |= ANCHOR_TOP | ANCHOR_BOTTOM | ANCHOR_LEFT | ANCHOR_RIGHT;
}
return label_anchor;
}

static struct slurp_output *output_from_box(const struct slurp_box *box, struct wl_list *outputs) {
struct slurp_output *output;
wl_list_for_each(output, outputs, link) {
Expand Down Expand Up @@ -887,21 +913,24 @@ int main(int argc, char *argv[]) {
.border = BORDER_COLOR,
.selection = SELECTION_COLOR,
.choice = BG_COLOR,
.label_text = LABEL_COLOR,
.label_background = LABEL_BG_COLOR,
},
.border_weight = 2,
.display_dimensions = false,
.restrict_selection = false,
.resizing_selection = false,
.fixed_aspect_ratio = false,
.aspect_ratio = 0,
.font_family = FONT_FAMILY
.font_family = FONT_FAMILY,
.label_anchor = ANCHOR_NONE
};

int opt;
char *format = "%x,%y %wx%h\n";
bool output_boxes = false;
int w, h;
while ((opt = getopt(argc, argv, "hdb:c:s:B:w:proa:f:F:")) != -1) {
while ((opt = getopt(argc, argv, "hdb:c:s:B:l:L:w:proa:f:F:P:")) != -1) {
switch (opt) {
case 'h':
printf("%s", usage);
Expand All @@ -921,12 +950,21 @@ int main(int argc, char *argv[]) {
case 'B':
state.colors.choice = parse_color(optarg);
break;
case 'l':
state.colors.label_text = parse_color(optarg);
break;
case 'L':
state.colors.label_background = parse_color(optarg);
break;
case 'f':
format = optarg;
break;
case 'F':
state.font_family = optarg;
break;
case 'P':
state.label_anchor = parse_label_anchor(optarg);
break;
case 'w': {
errno = 0;
char *endptr;
Expand Down
2 changes: 2 additions & 0 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ add_project_arguments('-Wno-unused-parameter', language: 'c')
cc = meson.get_compiler('c')

cairo = dependency('cairo')
math = cc.find_library('m')
realtime = cc.find_library('rt')
wayland_client = dependency('wayland-client')
wayland_cursor = dependency('wayland-cursor')
Expand All @@ -30,6 +31,7 @@ executable(
],
dependencies: [
cairo,
math,
realtime,
wayland_client,
wayland_cursor,
Expand Down
50 changes: 50 additions & 0 deletions render.c
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
#include <cairo/cairo.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#include "pool-buffer.h"
#include "render.h"
#include "slurp.h"

#define LABEL_BOX_PADDING 10
#define LABEL_HORIZONTAL_MARGING 10
#define LABEL_VERTICAL_MARGING 20

static void set_source_u32(cairo_t *cairo, uint32_t color) {
cairo_set_source_rgba(cairo, (color >> (3 * 8) & 0xFF) / 255.0,
(color >> (2 * 8) & 0xFF) / 255.0,
Expand All @@ -19,6 +24,45 @@ static void draw_rect(cairo_t *cairo, struct slurp_box *box, uint32_t color) {
box->width, box->height);
}

static void draw_rect_label(cairo_t *cairo, struct slurp_box *box, enum slurp_label_anchor anchor,
uint32_t text_color, uint32_t background_color, const char *font_family, const char *text) {
if (anchor == ANCHOR_NONE)
return;
cairo_select_font_face(cairo, font_family,
CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(cairo, 20);
cairo_text_extents_t extents;
cairo_text_extents(cairo, text, &extents);
struct slurp_box labelbox = { 0 };
labelbox.width = ceil(extents.width) + 2*LABEL_BOX_PADDING;
labelbox.height = ceil(extents.height) + 2*LABEL_BOX_PADDING;
labelbox.x = box->x + (box->width - labelbox.width) / 2;
labelbox.y = box->y + (box->height - labelbox.height) / 2;

if (anchor & ANCHOR_TOP && anchor & ANCHOR_BOTTOM) {
// Nothing to do
} else if (anchor & ANCHOR_TOP) {
labelbox.y = box->y + LABEL_VERTICAL_MARGING;
} else if (anchor & ANCHOR_BOTTOM) {
labelbox.y = box->y + box->height - LABEL_VERTICAL_MARGING - labelbox.height;
}
if (anchor & ANCHOR_LEFT && anchor & ANCHOR_RIGHT) {
// Nothing to do
} else if (anchor & ANCHOR_LEFT) {
labelbox.x = box->x + LABEL_HORIZONTAL_MARGING;
} else if (anchor & ANCHOR_RIGHT) {
labelbox.x = box->x + box->width - LABEL_HORIZONTAL_MARGING - labelbox.width;
}

draw_rect(cairo, &labelbox, background_color);
cairo_fill(cairo);
set_source_u32(cairo, text_color);
cairo_move_to(cairo, labelbox.x + LABEL_BOX_PADDING,
labelbox.y + LABEL_BOX_PADDING + ceil(extents.height));
cairo_show_text(cairo, text);
}

static void box_layout_to_output(struct slurp_box *box, struct slurp_output *output) {
box->x -= output->logical_geometry.x;
box->y -= output->logical_geometry.y;
Expand All @@ -43,6 +87,9 @@ void render(struct slurp_output *output) {
box_layout_to_output(&b, output);
draw_rect(cairo, &b, state->colors.choice);
cairo_fill(cairo);
if (b.label)
draw_rect_label(cairo, &b, state->label_anchor,
state->colors.label_text, state->colors.label_background, state->font_family, b.label);
}
}

Expand All @@ -64,6 +111,9 @@ void render(struct slurp_output *output) {

draw_rect(cairo, &b, state->colors.selection);
cairo_fill(cairo);
if (b.label)
draw_rect_label(cairo, &b, state->label_anchor,
state->colors.label_text, state->colors.label_background, state->font_family, b.label);

// Draw border
cairo_set_line_width(cairo, state->border_weight);
Expand Down
18 changes: 18 additions & 0 deletions slurp.1.scd
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ held, the selection is moved instead of being resized.
Set color for highlighting predefined rectangles from standard input when not
selected. Default is #FFFFFF40.

*-l* _color_
Set text color for labels. See *COLORS* for more detail.

*-L* _color_
Set background color for labels. See *COLORS* for more detail.

*-F* _font family_
Set the font family name when displaying the dimensions box. Only useful
when combined with the -d option. The available font family names guaranteed
Expand All @@ -56,6 +62,9 @@ held, the selection is moved instead of being resized.
*-f* _format_
Set format. See *FORMAT* for more detail.

*-P* _anchor_
Set postion anchor for the labels. See *ANCHOR* for more detail.

*-p*
Select a single pixel instead of a rectangle. This mode ignores any
predefined rectangles read from the standard input.
Expand Down Expand Up @@ -108,6 +117,15 @@ Interpreted sequences are:

The default format is "%x,%y %wx%h\\n".

# ANCHOR

Valid values are:

none, top, bottom, left, right, center

Combinations of these keywords chained together are possible, eg. top-right to
position the label in the top right corner.

# KEYBOARD CONTROLS

The following keyboard actions can be used during selection:
Expand Down