types: unify struct geometry and struct coord

It has been irking me greatly for a while that we have two structs that
are basically the same thing. Let's unify them into a vec2 type.

Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
Yuxuan Shui 2024-05-11 02:06:49 +01:00
parent 45dd915a61
commit ef94b1bbf8
No known key found for this signature in database
GPG Key ID: D3A4405BE6CC17F4
15 changed files with 175 additions and 182 deletions

View File

@ -87,7 +87,7 @@ struct backend_mask {
/// rounded.
double corner_radius;
/// Origin of the mask image, in the source image's coordinate.
struct coord origin;
ivec2 origin;
/// Whether the mask image should be inverted.
bool inverted;
};
@ -174,7 +174,7 @@ enum backend_command_source {
struct backend_command {
enum backend_command_op op;
struct coord origin;
ivec2 origin;
enum backend_command_source source;
union {
struct {
@ -258,9 +258,8 @@ struct backend_operations {
/// @param target an image handle, cannot be NULL.
/// @param args arguments for blit
/// @return whether the operation is successful
bool (*blit)(struct backend_base *backend_data, struct coord origin,
image_handle target, struct backend_blit_args *args)
attr_nonnull(1, 3, 4);
bool (*blit)(struct backend_base *backend_data, ivec2 origin, image_handle target,
struct backend_blit_args *args) attr_nonnull(1, 3, 4);
/// Blur a given region of a source image and store the result in the
/// target image.
@ -278,9 +277,8 @@ struct backend_operations {
/// @param target an image handle, cannot be NULL.
/// @param args argument for blur
/// @return whether the operation is successful
bool (*blur)(struct backend_base *backend_data, struct coord origin,
image_handle target, struct backend_blur_args *args)
attr_nonnull(1, 3, 4);
bool (*blur)(struct backend_base *backend_data, ivec2 origin, image_handle target,
struct backend_blur_args *args) attr_nonnull(1, 3, 4);
/// Direct copy of pixels from a source image on to the target image.
/// This is a simpler version of `blit`, without any effects. Note unlike `blit`,
@ -297,7 +295,7 @@ struct backend_operations {
/// @param source an image handle, cannot be NULL.
/// @param region the region to copy, in the source image's coordinate.
/// @return whether the operation is successful
bool (*copy_area)(struct backend_base *backend_data, struct coord origin,
bool (*copy_area)(struct backend_base *backend_data, ivec2 origin,
image_handle target, image_handle source, const region_t *region)
attr_nonnull(1, 3, 4, 5);
@ -320,7 +318,7 @@ struct backend_operations {
/// @param source an image handle, cannot be NULL.
/// @param region the region to copy, in the source image's coordinate.
/// @return whether the operation is successful
bool (*copy_area_quantize)(struct backend_base *backend_data, struct coord origin,
bool (*copy_area_quantize)(struct backend_base *backend_data, ivec2 origin,
image_handle target, image_handle source,
const region_t *region) attr_nonnull(1, 3, 4, 5);
@ -357,7 +355,7 @@ struct backend_operations {
/// @param format the format of the image
/// @param size the size of the image
image_handle (*new_image)(struct backend_base *backend_data,
enum backend_image_format format, geometry_t size)
enum backend_image_format format, ivec2 size)
attr_nonnull(1);
/// Bind a X pixmap to the backend's internal image data structure.

View File

@ -71,8 +71,8 @@ static void dummy_check_image(struct backend_base *base, image_handle image) {
}
}
bool dummy_blit(struct backend_base *base, struct coord origin attr_unused,
image_handle target, struct backend_blit_args *args) {
bool dummy_blit(struct backend_base *base, ivec2 origin attr_unused, image_handle target,
struct backend_blit_args *args) {
dummy_check_image(base, target);
dummy_check_image(base, args->source_image);
if (args->mask->image) {
@ -87,8 +87,8 @@ bool dummy_blit(struct backend_base *base, struct coord origin attr_unused,
return true;
}
bool dummy_blur(struct backend_base *base, struct coord origin attr_unused,
image_handle target, struct backend_blur_args *args) {
bool dummy_blur(struct backend_base *base, ivec2 origin attr_unused, image_handle target,
struct backend_blur_args *args) {
dummy_check_image(base, target);
dummy_check_image(base, args->source_image);
if (args->mask->image) {
@ -148,9 +148,8 @@ bool dummy_apply_alpha(struct backend_base *base, image_handle target,
return true;
}
bool dummy_copy_area(struct backend_base *base, struct coord origin attr_unused,
image_handle target, image_handle source,
const region_t *reg attr_unused) {
bool dummy_copy_area(struct backend_base *base, ivec2 origin attr_unused, image_handle target,
image_handle source, const region_t *reg attr_unused) {
dummy_check_image(base, target);
dummy_check_image(base, source);
return true;
@ -163,7 +162,7 @@ bool dummy_clear(struct backend_base *base, image_handle target,
}
image_handle dummy_new_image(struct backend_base *base, enum backend_image_format format,
struct geometry size attr_unused) {
ivec2 size attr_unused) {
auto new_img = ccalloc(1, struct dummy_image);
auto dummy = (struct dummy_data *)base;
list_insert_after(&dummy->non_pixmap_images, &new_img->siblings);

View File

@ -264,8 +264,8 @@ bool gl_dual_kawase_blur(double opacity, struct gl_blur_context *bctx,
return true;
}
static bool gl_blur_context_preallocate_textures(struct gl_blur_context *bctx,
struct geometry source_size) {
static bool
gl_blur_context_preallocate_textures(struct gl_blur_context *bctx, ivec2 source_size) {
if (source_size.width != bctx->fb_width || source_size.height != bctx->fb_height) {
// Resize the temporary textures used for blur in case the root
// size changed
@ -312,7 +312,7 @@ static bool gl_blur_context_preallocate_textures(struct gl_blur_context *bctx,
return true;
}
bool gl_blur(struct backend_base *base, struct coord origin, image_handle target_,
bool gl_blur(struct backend_base *base, ivec2 origin, image_handle target_,
struct backend_blur_args *args) {
auto gd = (struct gl_data *)base;
auto target = (struct gl_texture *)target_;
@ -339,7 +339,7 @@ bool gl_blur(struct backend_base *base, struct coord origin, image_handle target
}
if (!gl_blur_context_preallocate_textures(
bctx, (struct geometry){source->width, source->height})) {
bctx, (ivec2){source->width, source->height})) {
return false;
}

View File

@ -475,7 +475,7 @@ static void gl_blit_inner(GLuint target_fbo, int nrects, GLint *coord, GLuint *i
gl_check_err();
}
void gl_mask_rects_to_coords(struct coord origin, struct coord mask_origin, int nrects,
void gl_mask_rects_to_coords(ivec2 origin, ivec2 mask_origin, int nrects,
const rect_t *rects, GLint *coord, GLuint *indices) {
for (ptrdiff_t i = 0; i < nrects; i++) {
// Rectangle in source image coordinates
@ -522,9 +522,9 @@ static inline void gl_y_flip_texture(int nrects, GLint *coord, GLint texture_hei
/// Lower `struct backend_blit_args` into a list of GL coordinates, vertex indices, a
/// shader, and uniforms.
static int gl_lower_blit_args(struct gl_data *gd, struct coord origin,
struct backend_blit_args *args, GLint **coord, GLuint **indices,
struct gl_shader **shader, struct gl_uniform_value *uniforms) {
static int gl_lower_blit_args(struct gl_data *gd, ivec2 origin, struct backend_blit_args *args,
GLint **coord, GLuint **indices, struct gl_shader **shader,
struct gl_uniform_value *uniforms) {
auto img = (struct gl_texture *)args->source_image;
int nrects;
const rect_t *rects;
@ -533,7 +533,7 @@ static int gl_lower_blit_args(struct gl_data *gd, struct coord origin,
// Nothing to paint
return 0;
}
struct coord mask_origin = args->mask->origin;
ivec2 mask_origin = args->mask->origin;
*coord = ccalloc(nrects * 16, GLint);
*indices = ccalloc(nrects * 6, GLuint);
gl_mask_rects_to_coords(origin, mask_origin, nrects, rects, *coord, *indices);
@ -599,7 +599,7 @@ static int gl_lower_blit_args(struct gl_data *gd, struct coord origin,
return nrects;
}
bool gl_blit(backend_t *base, struct coord origin, image_handle target_,
bool gl_blit(backend_t *base, ivec2 origin, image_handle target_,
struct backend_blit_args *args) {
auto gd = (struct gl_data *)base;
auto source = (struct gl_texture *)args->source_image;
@ -638,8 +638,8 @@ bool gl_blit(backend_t *base, struct coord origin, image_handle target_,
/// Copy areas by glBlitFramebuffer. This is only used to copy data from the back
/// buffer.
static bool gl_copy_area_blit_fbo(struct gl_data *gd, struct coord origin,
image_handle target, const region_t *region) {
static bool gl_copy_area_blit_fbo(struct gl_data *gd, ivec2 origin, image_handle target,
const region_t *region) {
gl_bind_image_to_fbo(gd, target);
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
@ -662,7 +662,7 @@ static bool gl_copy_area_blit_fbo(struct gl_data *gd, struct coord origin,
}
/// Copy areas by drawing. This is the common path to copy from one texture to another.
static bool gl_copy_area_draw(struct gl_data *gd, struct coord origin,
static bool gl_copy_area_draw(struct gl_data *gd, ivec2 origin,
image_handle target_handle, image_handle source_handle,
struct gl_shader *shader, const region_t *region) {
auto source = (struct gl_texture *)source_handle;
@ -677,7 +677,7 @@ static bool gl_copy_area_draw(struct gl_data *gd, struct coord origin,
auto coord = ccalloc(16 * nrects, GLint);
auto indices = ccalloc(6 * nrects, GLuint);
gl_mask_rects_to_coords(origin, (struct coord){}, nrects, rects, coord, indices);
gl_mask_rects_to_coords(origin, (ivec2){}, nrects, rects, coord, indices);
if (!target->y_inverted) {
gl_y_flip_target(nrects, coord, target->height);
}
@ -695,7 +695,7 @@ static bool gl_copy_area_draw(struct gl_data *gd, struct coord origin,
return true;
}
bool gl_copy_area(backend_t *backend_data, struct coord origin, image_handle target,
bool gl_copy_area(backend_t *backend_data, ivec2 origin, image_handle target,
image_handle source, const region_t *region) {
auto gd = (struct gl_data *)backend_data;
if ((struct gl_texture *)source == &gd->back_image) {
@ -704,9 +704,8 @@ bool gl_copy_area(backend_t *backend_data, struct coord origin, image_handle tar
return gl_copy_area_draw(gd, origin, target, source, &gd->copy_area_prog, region);
}
bool gl_copy_area_quantize(backend_t *backend_data, struct coord origin,
image_handle target_handle, image_handle source_handle,
const region_t *region) {
bool gl_copy_area_quantize(backend_t *backend_data, ivec2 origin, image_handle target_handle,
image_handle source_handle, const region_t *region) {
auto gd = (struct gl_data *)backend_data;
auto target = (struct gl_texture *)target_handle;
auto source = (struct gl_texture *)source_handle;
@ -1062,7 +1061,7 @@ image_handle gl_back_buffer(struct backend_base *base) {
}
image_handle gl_new_image(backend_t *backend_data attr_unused,
enum backend_image_format format, geometry_t size) {
enum backend_image_format format, ivec2 size) {
auto tex = ccalloc(1, struct gl_texture);
log_trace("Creating texture %dx%d", size.width, size.height);
tex->format = format;

View File

@ -126,18 +126,18 @@ void gl_prepare(backend_t *base, const region_t *reg);
/// @param[in] rects mask rectangles, in mask coordinates
/// @param[out] coord OpenGL vertex coordinates, suitable for creating VAO/VBO
/// @param[out] indices OpenGL vertex indices, suitable for creating VAO/VBO
void gl_mask_rects_to_coords(struct coord origin, struct coord mask_origin, int nrects,
void gl_mask_rects_to_coords(ivec2 origin, ivec2 mask_origin, int nrects,
const rect_t *rects, GLint *coord, GLuint *indices);
/// Like `gl_mask_rects_to_coords`, but with `origin` and `mask_origin` set to 0. i.e. all
/// coordinates are in the same space.
static inline void gl_mask_rects_to_coords_simple(int nrects, const rect_t *rects,
GLint *coord, GLuint *indices) {
return gl_mask_rects_to_coords((struct coord){0, 0}, (struct coord){0, 0}, nrects,
rects, coord, indices);
return gl_mask_rects_to_coords((ivec2){0, 0}, (ivec2){0, 0}, nrects, rects, coord,
indices);
}
GLuint gl_create_shader(GLenum shader_type, const char *shader_str);
GLuint gl_create_program(const GLuint *const shaders, int nshaders);
GLuint gl_create_program(const GLuint *shaders, int nshaders);
GLuint gl_create_program_from_str(const char *vert_shader_str, const char *frag_shader_str);
GLuint gl_create_program_from_strv(const char **vert_shaders, const char **frag_shaders);
void *gl_create_window_shader(backend_t *backend_data, const char *source);
@ -145,10 +145,10 @@ void gl_destroy_window_shader(backend_t *backend_data, void *shader);
uint64_t gl_get_shader_attributes(backend_t *backend_data, void *shader);
bool gl_last_render_time(backend_t *backend_data, struct timespec *time);
bool gl_blit(backend_t *base, struct coord origin, image_handle target,
bool gl_blit(backend_t *base, ivec2 origin, image_handle target,
struct backend_blit_args *args);
image_handle gl_new_image(backend_t *backend_data attr_unused,
enum backend_image_format format, geometry_t size);
enum backend_image_format format, ivec2 size);
bool gl_clear(backend_t *backend_data, image_handle target, struct color color);
void gl_root_change(backend_t *base, session_t *);
@ -164,13 +164,12 @@ xcb_pixmap_t gl_release_image(backend_t *base, image_handle image);
image_handle gl_clone(backend_t *base, image_handle image, const region_t *reg_visible);
bool gl_blur(struct backend_base *gd, struct coord origin, image_handle target,
bool gl_blur(struct backend_base *gd, ivec2 origin, image_handle target,
struct backend_blur_args *args);
bool gl_copy_area(backend_t *backend_data, struct coord origin, image_handle target,
bool gl_copy_area(backend_t *backend_data, ivec2 origin, image_handle target,
image_handle source, const region_t *region);
bool gl_copy_area_quantize(backend_t *backend_data, struct coord origin,
image_handle target_handle, image_handle source_handle,
const region_t *region);
bool gl_copy_area_quantize(backend_t *backend_data, ivec2 origin, image_handle target_handle,
image_handle source_handle, const region_t *region);
bool gl_apply_alpha(backend_t *base, image_handle target, double alpha, const region_t *reg_op);
image_handle gl_back_buffer(struct backend_base *base);
uint32_t gl_image_capabilities(backend_t *base, image_handle img);

View File

@ -28,7 +28,7 @@
#include "x.h"
struct xrender_image_data_inner {
struct geometry size;
ivec2 size;
enum backend_image_format format;
struct xrender_rounded_rectangle_cache *rounded_rectangle;
// Pixmap that the client window draws to,
@ -194,9 +194,8 @@ static inline void xrender_set_picture_repeat(struct xrender_data *xd,
}
static inline void
xrender_record_back_damage(struct xrender_data *xd,
struct xrender_image_data_inner *target, struct coord origin,
struct coord mask_origin, const region_t *region) {
xrender_record_back_damage(struct xrender_data *xd, struct xrender_image_data_inner *target,
ivec2 origin, ivec2 mask_origin, const region_t *region) {
if (target == &xd->back_image && xd->vsync) {
pixman_region32_translate(&xd->back_damaged, -origin.x - mask_origin.x,
-origin.y - mask_origin.y);
@ -214,8 +213,7 @@ xrender_record_back_damage(struct xrender_data *xd,
/// @param allocated whether the returned picture is newly allocated
static xcb_render_picture_t
xrender_process_mask(struct xrender_data *xd, struct backend_mask *mask, rect_t extent,
xcb_render_picture_t alpha_pict, struct coord *new_origin,
bool *allocated) {
xcb_render_picture_t alpha_pict, ivec2 *new_origin, bool *allocated) {
auto inner = (struct xrender_image_data_inner *)mask->image;
if (!inner) {
*allocated = false;
@ -229,7 +227,7 @@ xrender_process_mask(struct xrender_data *xd, struct backend_mask *mask, rect_t
auto const h_u16 = to_u16_checked(extent.y2 - extent.y1);
*allocated = true;
*new_origin =
(struct coord){.x = extent.x1 + mask->origin.x, .y = extent.y1 + mask->origin.y};
(ivec2){.x = extent.x1 + mask->origin.x, .y = extent.y1 + mask->origin.y};
x_clear_picture_clip_region(xd->base.c, inner->pict);
auto ret = x_create_picture_with_pictfmt(
xd->base.c, extent.x2 - extent.x1, extent.y2 - extent.y1, inner->pictfmt,
@ -271,7 +269,7 @@ xrender_process_mask(struct xrender_data *xd, struct backend_mask *mask, rect_t
return ret;
}
static bool xrender_blit(struct backend_base *base, struct coord origin,
static bool xrender_blit(struct backend_base *base, ivec2 origin,
image_handle target_handle, struct backend_blit_args *args) {
auto xd = (struct xrender_data *)base;
auto inner = (struct xrender_image_data_inner *)args->source_image;
@ -470,9 +468,9 @@ xrender_clear(struct backend_base *base, image_handle target_handle, struct colo
return true;
}
static bool xrender_copy_area(struct backend_base *base, struct coord origin,
image_handle target_handle, image_handle source_handle,
const region_t *region) {
static bool
xrender_copy_area(struct backend_base *base, ivec2 origin, image_handle target_handle,
image_handle source_handle, const region_t *region) {
auto xd = (struct xrender_data *)base;
auto source = (struct xrender_image_data_inner *)source_handle;
auto target = (struct xrender_image_data_inner *)target_handle;
@ -485,11 +483,11 @@ static bool xrender_copy_area(struct backend_base *base, struct coord origin,
to_i16_checked(extent->x1), to_i16_checked(extent->y1), 0, 0,
to_i16_checked(origin.x + extent->x1), to_i16_checked(origin.y + extent->y1),
to_u16_checked(extent->x2 - extent->x1), to_u16_checked(extent->y2 - extent->y1));
xrender_record_back_damage(xd, target, origin, (struct coord){0, 0}, region);
xrender_record_back_damage(xd, target, origin, (ivec2){0, 0}, region);
return true;
}
static bool xrender_blur(struct backend_base *base, struct coord origin,
static bool xrender_blur(struct backend_base *base, ivec2 origin,
image_handle target_handle, struct backend_blur_args *args) {
auto bctx = (struct xrender_blur_context *)args->blur_context;
auto mask = (struct xrender_image_data_inner *)args->mask->image;
@ -559,7 +557,7 @@ static bool xrender_blur(struct backend_base *base, struct coord origin,
// Sampling the 1x1 alpha pict out-of-bound while the X server is under
// heavy load, which it will be if blur is enabled, produces unpredictable
// results... This is a workaround for that.
mask_pict_origin = (struct coord){0, 0};
mask_pict_origin = (ivec2){0, 0};
}
x_set_picture_clip_region(c, src_pict, 0, 0, &reg_op_resized);
x_set_picture_clip_region(
@ -575,8 +573,8 @@ static bool xrender_blur(struct backend_base *base, struct coord origin,
// (if source != target)
// source -(pass 1)-> target
xcb_render_picture_t dst_pict = target == source ? tmp_picture[0] : target->pict;
struct coord src_origin = {.x = extent_resized->x1, .y = extent_resized->y1};
struct coord dst_origin = {};
ivec2 src_origin = {.x = extent_resized->x1, .y = extent_resized->y1};
ivec2 dst_origin = {};
int npasses = bctx->x_blur_kernel_count;
if (source == target && npasses == 1) {
npasses = 2;
@ -613,14 +611,14 @@ static bool xrender_blur(struct backend_base *base, struct coord origin,
if (i + 1 == npasses - 1) {
// Intermediary to target
dst_pict = target->pict;
dst_origin = (struct coord){.x = origin.x + extent_resized->x1,
.y = origin.y + extent_resized->y1};
dst_origin = (ivec2){.x = origin.x + extent_resized->x1,
.y = origin.y + extent_resized->y1};
} else {
// Intermediary to intermediary
dst_pict = next_tmp;
dst_origin = (struct coord){.x = 0, .y = 0};
dst_origin = (ivec2){.x = 0, .y = 0};
}
src_origin = (struct coord){.x = 0, .y = 0};
src_origin = (ivec2){.x = 0, .y = 0};
}
if (mask_allocated) {
@ -648,7 +646,7 @@ xrender_bind_pixmap(backend_t *base, xcb_pixmap_t pixmap, struct xvisual_info fm
auto img = ccalloc(1, struct xrender_image_data_inner);
img->depth = (uint8_t)fmt.visual_depth;
img->has_alpha = fmt.alpha_size > 0;
img->size = (struct geometry){
img->size = (ivec2){
.width = r->width,
.height = r->height,
};
@ -786,7 +784,7 @@ static bool xrender_apply_alpha(struct backend_base *base, image_handle image,
xcb_render_composite(base->c->c, XCB_RENDER_PICT_OP_OUT_REVERSE, alpha_pict, XCB_NONE,
img->pict, 0, 0, 0, 0, 0, 0, to_u16_checked(img->size.width),
to_u16_checked(img->size.height));
static const struct coord zero = {0, 0};
static const ivec2 zero = {};
xrender_record_back_damage(xd, img, zero, zero, reg_op);
return true;
}
@ -948,8 +946,8 @@ err:
return NULL;
}
static image_handle xrender_new_image(struct backend_base *base,
enum backend_image_format format, struct geometry size) {
static image_handle
xrender_new_image(struct backend_base *base, enum backend_image_format format, ivec2 size) {
auto xd = (struct xrender_data *)base;
auto img = ccalloc(1, struct xrender_image_data_inner);
img->format = format;

View File

@ -1835,8 +1835,7 @@ static void draw_callback_impl(EV_P_ session_t *ps, int revents attr_unused) {
(uint64_t)now.tv_sec * 1000000UL + (uint64_t)now.tv_nsec / 1000;
layout_manager_append_layout(
ps->layout_manager, ps->wm, ps->root_image_generation,
(struct geometry){.width = ps->root_width,
.height = ps->root_height});
(ivec2){.width = ps->root_width, .height = ps->root_height});
bool succeeded = renderer_render(
ps->renderer, ps->backend_data, ps->root_image,
ps->layout_manager, ps->command_builder,

View File

@ -124,7 +124,7 @@ static inline void resize_region_in_place(region_t *region, int dx, int dy) {
return _resize_region(region, region, dx, dy);
}
static inline rect_t region_translate_rect(rect_t rect, struct coord origin) {
static inline rect_t region_translate_rect(rect_t rect, ivec2 origin) {
return (rect_t){
.x1 = rect.x1 + origin.x,
.y1 = rect.y1 + origin.y,
@ -134,23 +134,21 @@ static inline rect_t region_translate_rect(rect_t rect, struct coord origin) {
}
/// Subtract `other`, placed at `origin`, from `region`.
static inline void
region_subtract(region_t *region, struct coord origin, const region_t *other) {
static inline void region_subtract(region_t *region, ivec2 origin, const region_t *other) {
pixman_region32_translate(region, -origin.x, -origin.y);
pixman_region32_subtract(region, region, other);
pixman_region32_translate(region, origin.x, origin.y);
}
/// Union `region` with `other` placed at `origin`.
static inline void region_union(region_t *region, struct coord origin, const region_t *other) {
static inline void region_union(region_t *region, ivec2 origin, const region_t *other) {
pixman_region32_translate(region, -origin.x, -origin.y);
pixman_region32_union(region, region, other);
pixman_region32_translate(region, origin.x, origin.y);
}
/// Intersect `region` with `other` placed at `origin`.
static inline void
region_intersect(region_t *region, struct coord origin, const region_t *other) {
static inline void region_intersect(region_t *region, ivec2 origin, const region_t *other) {
pixman_region32_translate(region, -origin.x, -origin.y);
pixman_region32_intersect(region, region, other);
pixman_region32_translate(region, origin.x, origin.y);
@ -160,15 +158,14 @@ region_intersect(region_t *region, struct coord origin, const region_t *other) {
/// `origin2`, and union the result into `result`.
///
/// @param scratch a region to store temporary results
static inline void
region_symmetric_difference(region_t *result, region_t *scratch, struct coord origin1,
const region_t *region1, struct coord origin2,
const region_t *region2) {
static inline void region_symmetric_difference(region_t *result, region_t *scratch,
ivec2 origin1, const region_t *region1,
ivec2 origin2, const region_t *region2) {
pixman_region32_copy(scratch, region1);
region_subtract(scratch, coord_sub(origin2, origin1), region2);
region_subtract(scratch, ivec2_sub(origin2, origin1), region2);
region_union(result, origin1, scratch);
pixman_region32_copy(scratch, region2);
region_subtract(scratch, coord_sub(origin1, origin2), region1);
region_subtract(scratch, ivec2_sub(origin1, origin2), region1);
region_union(result, origin2, scratch);
}

View File

@ -48,7 +48,7 @@ commands_for_window_body(struct layer *layer, struct backend_command *cmd,
.max_brightness = max_brightness};
cmd->mask.inverted = false;
cmd->mask.corner_radius = 0;
cmd->mask.origin = (struct coord){};
cmd->mask.origin = (ivec2){};
pixman_region32_copy(&cmd->mask.region, &w->bounding_shape);
if (w->frame_opacity < 1) {
pixman_region32_subtract(&cmd->mask.region, &cmd->mask.region, frame_region);
@ -77,7 +77,7 @@ commands_for_window_body(struct layer *layer, struct backend_command *cmd,
cmd->blit = cmd[1].blit;
cmd->blit.mask = &cmd->mask;
cmd->blit.opacity *= w->frame_opacity;
cmd->mask.origin = (struct coord){};
cmd->mask.origin = (ivec2){};
cmd->mask.inverted = false;
cmd->mask.corner_radius = 0;
pixman_region32_copy(&cmd->mask.region, frame_region);
@ -144,14 +144,12 @@ command_for_shadow(struct layer *layer, struct backend_command *cmd,
-layer->shadow_origin.y);
cmd->mask.corner_radius = w->corner_radius;
cmd->mask.inverted = true;
cmd->mask.origin = (struct coord){};
cmd->mask.origin = (ivec2){};
cmd->need_mask_image = w->corner_radius > 0;
if (cmd->need_mask_image) {
// If we use the window's mask image, we need to align the
// mask region's origin with it.
cmd->mask.origin =
(struct coord){.x = layer->origin.x - layer->shadow_origin.x,
.y = layer->origin.y - layer->shadow_origin.y};
cmd->mask.origin = ivec2_sub(layer->origin, layer->shadow_origin);
pixman_region32_translate(&cmd->mask.region, -cmd->mask.origin.x,
-cmd->mask.origin.y);
}
@ -176,10 +174,10 @@ command_for_blur(struct layer *layer, struct backend_command *cmd,
return 0;
}
cmd->op = BACKEND_COMMAND_BLUR;
cmd->origin = (struct coord){};
cmd->origin = (ivec2){};
cmd->blur.opacity = layer->blur_opacity;
cmd->blur.mask = &cmd->mask;
cmd->mask.origin = (struct coord){.x = layer->origin.x, .y = layer->origin.y};
cmd->mask.origin = (ivec2){.x = layer->origin.x, .y = layer->origin.y};
cmd->need_mask_image = w->corner_radius > 0;
cmd->mask.corner_radius = w->corner_radius;
cmd->mask.inverted = false;
@ -230,10 +228,7 @@ command_builder_apply_transparent_clipping(struct layout *layout, region_t *scra
if (i->op == BACKEND_COMMAND_BLUR ||
(i->op == BACKEND_COMMAND_BLIT &&
i->source != BACKEND_COMMAND_SOURCE_BACKGROUND)) {
struct coord scratch_origin = {
.x = -i->origin.x - i->mask.origin.x,
.y = -i->origin.y - i->mask.origin.y,
};
auto scratch_origin = ivec2_sub(ivec2_neg(i->origin), i->mask.origin);
region_subtract(&i->mask.region, scratch_origin, scratch_region);
}
if (i->op == BACKEND_COMMAND_BLIT &&
@ -260,10 +255,7 @@ command_builder_apply_shadow_clipping(struct layout *layout, region_t *scratch_r
clip_shadow_above = layer->win->clip_shadow_above;
}
struct coord mask_origin = {
.x = i->mask.origin.x + i->origin.x,
.y = i->mask.origin.y + i->origin.y,
};
auto mask_origin = ivec2_add(i->mask.origin, i->origin);
if (i->op == BACKEND_COMMAND_BLUR) {
region_subtract(scratch_region, mask_origin, &i->mask.region);
} else if (i->op == BACKEND_COMMAND_BLIT) {
@ -410,7 +402,7 @@ void command_builder_build(struct command_builder *cb, struct layout *layout, bo
// Command for the desktop background
cmd->op = BACKEND_COMMAND_COPY_AREA;
cmd->source = BACKEND_COMMAND_SOURCE_BACKGROUND;
cmd->origin = (struct coord){};
cmd->origin = (ivec2){};
pixman_region32_reset(
&cmd->mask.region,
(rect_t[]){{.x1 = 0, .y1 = 0, .x2 = layout->size.width, .y2 = layout->size.height}});

View File

@ -45,7 +45,7 @@ layer_compare(const struct layer *past_layer, const struct backend_command *past
for (unsigned i = 0; i < past_layer->number_of_commands; i++) {
auto cmd1 = &past_layer_cmd[i];
auto cmd2 = &curr_layer_cmd[i];
if (cmd1->op != cmd2->op || !coord_eq(cmd1->origin, cmd2->origin) ||
if (cmd1->op != cmd2->op || !ivec2_eq(cmd1->origin, cmd2->origin) ||
cmd1->source != cmd2->source) {
return false;
}
@ -57,7 +57,7 @@ layer_compare(const struct layer *past_layer, const struct backend_command *past
static inline void region_union_render_layer(region_t *region, const struct layer *layer,
const struct backend_command *cmds) {
for (auto i = cmds; i < &cmds[layer->number_of_commands]; i++) {
region_union(region, coord_add(i->origin, i->mask.origin), &i->mask.region);
region_union(region, ivec2_add(i->origin, i->mask.origin), &i->mask.region);
}
}
@ -65,8 +65,8 @@ static inline void
command_blit_damage(region_t *damage, region_t *scratch_region, struct backend_command *cmd1,
struct backend_command *cmd2, const struct layout_manager *lm,
unsigned layer_index, unsigned buffer_age) {
auto origin1 = coord_add(cmd1->origin, cmd1->mask.origin);
auto origin2 = coord_add(cmd2->origin, cmd2->mask.origin);
auto origin1 = ivec2_add(cmd1->origin, cmd1->mask.origin);
auto origin2 = ivec2_add(cmd2->origin, cmd2->mask.origin);
// clang-format off
// First part, if any blit argument that would affect the whole image changed
if (cmd1->blit.dim != cmd2->blit.dim ||
@ -107,11 +107,11 @@ command_blit_damage(region_t *damage, region_t *scratch_region, struct backend_c
}
}
static inline void
command_blur_damage(region_t *damage, region_t *scratch_region, struct backend_command *cmd1,
struct backend_command *cmd2, struct geometry blur_size) {
auto origin1 = coord_add(cmd1->origin, cmd1->mask.origin);
auto origin2 = coord_add(cmd2->origin, cmd2->mask.origin);
static inline void command_blur_damage(region_t *damage, region_t *scratch_region,
struct backend_command *cmd1,
struct backend_command *cmd2, ivec2 blur_size) {
auto origin1 = ivec2_add(cmd1->origin, cmd1->mask.origin);
auto origin2 = ivec2_add(cmd2->origin, cmd2->mask.origin);
if (cmd1->blur.opacity != cmd2->blur.opacity) {
region_union(damage, origin1, &cmd1->mask.region);
region_union(damage, origin2, &cmd2->mask.region);
@ -134,7 +134,7 @@ command_blur_damage(region_t *damage, region_t *scratch_region, struct backend_c
/// Do the first step of render planning, collecting damages and calculating which
/// parts of the final screen will be affected by the damages.
void layout_manager_damage(struct layout_manager *lm, unsigned buffer_age,
struct geometry blur_size, region_t *damage) {
ivec2 blur_size, region_t *damage) {
log_trace("Damage for buffer age %d", buffer_age);
unsigned past_layer_rank = 0, curr_layer_rank = 0;
auto past_layout = layout_manager_layout(lm, buffer_age);
@ -294,7 +294,7 @@ void layout_manager_damage(struct layout_manager *lm, unsigned buffer_age,
}
void commands_cull_with_damage(struct layout *layout, const region_t *damage,
struct geometry blur_size, struct backend_mask *culled_mask) {
ivec2 blur_size, struct backend_mask *culled_mask) {
// This may sound silly, and probably actually is. Why do GPU's job on the CPU?
// Isn't the GPU supposed to be the one that does culling, depth testing etc.?
//
@ -317,16 +317,16 @@ void commands_cull_with_damage(struct layout *layout, const region_t *damage,
pixman_region32_copy(&scratch_region, damage);
for (int i = to_int_checked(layout->number_of_commands - 1); i >= 0; i--) {
auto cmd = &layout->commands[i];
struct coord mask_origin;
ivec2 mask_origin;
if (cmd->op != BACKEND_COMMAND_COPY_AREA) {
mask_origin = coord_add(cmd->origin, cmd->mask.origin);
mask_origin = ivec2_add(cmd->origin, cmd->mask.origin);
} else {
mask_origin = cmd->origin;
}
culled_mask[i] = cmd->mask;
pixman_region32_init(&culled_mask[i].region);
pixman_region32_copy(&culled_mask[i].region, &cmd->mask.region);
region_intersect(&culled_mask[i].region, coord_neg(mask_origin),
region_intersect(&culled_mask[i].region, ivec2_neg(mask_origin),
&scratch_region);
switch (cmd->op) {
case BACKEND_COMMAND_BLIT:

View File

@ -17,7 +17,7 @@ struct backend_mask;
/// initialized regions. This function will initialize their regions.
/// These masks MUST NOT be freed until you call `commands_uncull`.
void commands_cull_with_damage(struct layout *layout, const region_t *damage,
struct geometry blur_size, struct backend_mask *culled_mask);
ivec2 blur_size, struct backend_mask *culled_mask);
/// Un-do the effect of `commands_cull_with_damage`
void commands_uncull(struct layout *layout);
@ -36,4 +36,4 @@ void commands_uncull(struct layout *layout);
/// Note `layout_manager_damage` cannot take desktop background change into
/// account.
void layout_manager_damage(struct layout_manager *lm, unsigned buffer_age,
struct geometry blur_size, region_t *damage);
ivec2 blur_size, region_t *damage);

View File

@ -7,7 +7,6 @@
#include "common.h"
#include "list.h"
#include "region.h"
#include "transition.h"
#include "types.h"
#include "utils.h"
#include "win.h"
@ -37,23 +36,22 @@ struct layout_manager {
/// Compute layout of a layer from a window. Returns false if the window is not
/// visible / should not be rendered. `out_layer` is modified either way.
static bool
layer_from_window(struct layer *out_layer, struct managed_win *w, struct geometry size) {
static bool layer_from_window(struct layer *out_layer, struct managed_win *w, ivec2 size) {
bool to_paint = false;
if (!w->ever_damaged || w->paint_excluded) {
goto out;
}
out_layer->origin = (struct coord){.x = w->g.x, .y = w->g.y};
out_layer->size = (struct geometry){.width = w->widthb, .height = w->heightb};
out_layer->origin = (ivec2){.x = w->g.x, .y = w->g.y};
out_layer->size = (ivec2){.width = w->widthb, .height = w->heightb};
if (w->shadow) {
out_layer->shadow_origin =
(struct coord){.x = w->g.x + w->shadow_dx, .y = w->g.y + w->shadow_dy};
(ivec2){.x = w->g.x + w->shadow_dx, .y = w->g.y + w->shadow_dy};
out_layer->shadow_size =
(struct geometry){.width = w->shadow_width, .height = w->shadow_height};
(ivec2){.width = w->shadow_width, .height = w->shadow_height};
} else {
out_layer->shadow_origin = (struct coord){};
out_layer->shadow_size = (struct geometry){};
out_layer->shadow_origin = (ivec2){};
out_layer->shadow_size = (ivec2){};
}
if (out_layer->size.width <= 0 || out_layer->size.height <= 0) {
goto out;
@ -143,7 +141,7 @@ void layout_manager_free(struct layout_manager *lm) {
// above.
void layout_manager_append_layout(struct layout_manager *lm, struct wm *wm,
uint64_t root_pixmap_generation, struct geometry size) {
uint64_t root_pixmap_generation, ivec2 size) {
auto prev_layout = &lm->layouts[lm->current];
lm->current = (lm->current + 1) % lm->max_buffer_age;
auto layout = &lm->layouts[lm->current];

View File

@ -30,13 +30,13 @@ struct layer {
/// Damaged region of this layer, in screen coordinates
region_t damaged;
/// Origin (the top left outmost corner) of the window in screen coordinates
struct coord origin;
ivec2 origin;
/// Size of the window
struct geometry size;
ivec2 size;
/// Origin of the shadow in screen coordinates
struct coord shadow_origin;
ivec2 shadow_origin;
/// Size of the shadow
struct geometry shadow_size;
ivec2 shadow_size;
/// Opacity of this window
float opacity;
/// Opacity of the background blur of this window
@ -70,7 +70,7 @@ struct layer {
/// Layout of windows at a specific frame
struct layout {
struct geometry size;
ivec2 size;
/// The root image generation, see `struct session::root_image_generation`
uint64_t root_image_generation;
/// Number of layers in `layers`
@ -98,7 +98,7 @@ struct layout_manager;
/// layouts, with its size chosen at creation time. Calling this will push at new layout
/// at the end of the ring buffer, and remove the oldest layout if the buffer is full.
void layout_manager_append_layout(struct layout_manager *lm, struct wm *wm,
uint64_t root_image_generation, struct geometry size);
uint64_t root_image_generation, ivec2 size);
/// Get the layout `age` frames into the past. Age `0` is the most recently appended
/// layout.
struct layout *layout_manager_layout(struct layout_manager *lm, unsigned age);

View File

@ -31,7 +31,7 @@ struct renderer {
int max_buffer_age;
/// 1x1 shadow colored xrender picture
xcb_render_picture_t shadow_pixel;
struct geometry canvas_size;
ivec2 canvas_size;
/// Format to use for back_image and intermediate images
enum backend_image_format format;
struct color shadow_color;
@ -87,18 +87,18 @@ renderer_init(struct renderer *renderer, struct backend_base *backend,
: BACKEND_IMAGE_FORMAT_PIXMAP;
renderer->back_image = NULL;
renderer->white_image =
backend->ops->new_image(backend, renderer->format, (struct geometry){1, 1});
backend->ops->new_image(backend, renderer->format, (ivec2){1, 1});
if (!renderer->white_image || !backend->ops->clear(backend, renderer->white_image,
(struct color){1, 1, 1, 1})) {
return false;
}
renderer->black_image =
backend->ops->new_image(backend, renderer->format, (struct geometry){1, 1});
backend->ops->new_image(backend, renderer->format, (ivec2){1, 1});
if (!renderer->black_image || !backend->ops->clear(backend, renderer->black_image,
(struct color){0, 0, 0, 1})) {
return false;
}
renderer->canvas_size = (struct geometry){0, 0};
renderer->canvas_size = (ivec2){0, 0};
if (shadow_radius > 0) {
struct gaussian_blur_args args = {
.size = (int)shadow_radius,
@ -141,8 +141,8 @@ struct renderer *renderer_new(struct backend_base *backend, double shadow_radius
return renderer;
}
static inline bool renderer_set_root_size(struct renderer *r, struct backend_base *backend,
struct geometry root_size) {
static inline bool
renderer_set_root_size(struct renderer *r, struct backend_base *backend, ivec2 root_size) {
if (r->canvas_size.width == root_size.width &&
r->canvas_size.height == root_size.height) {
return true;
@ -155,7 +155,7 @@ static inline bool renderer_set_root_size(struct renderer *r, struct backend_bas
r->canvas_size = root_size;
return true;
}
r->canvas_size = (struct geometry){0, 0};
r->canvas_size = (ivec2){0, 0};
if (r->monitor_repaint_copy) {
for (int i = 0; i < r->max_buffer_age; i++) {
backend->ops->release_image(backend, r->monitor_repaint_copy[i]);
@ -168,7 +168,7 @@ static inline bool renderer_set_root_size(struct renderer *r, struct backend_bas
static bool
renderer_bind_mask(struct renderer *r, struct backend_base *backend, struct managed_win *w) {
struct geometry size = {.width = w->widthb, .height = w->heightb};
ivec2 size = {.width = w->widthb, .height = w->heightb};
bool succeeded = false;
auto image = backend->ops->new_image(backend, BACKEND_IMAGE_FORMAT_MASK, size);
if (!image || !backend->ops->clear(backend, image, (struct color){0, 0, 0, 0})) {
@ -178,7 +178,7 @@ renderer_bind_mask(struct renderer *r, struct backend_base *backend, struct mana
auto bound_region_local = win_get_bounding_shape_global_by_val(w);
pixman_region32_translate(&bound_region_local, -w->g.x, -w->g.y);
succeeded = backend->ops->copy_area(backend, (struct coord){0, 0}, (image_handle)image,
succeeded = backend->ops->copy_area(backend, (ivec2){0, 0}, (image_handle)image,
r->white_image, &bound_region_local);
pixman_region32_fini(&bound_region_local);
if (!succeeded) {
@ -195,9 +195,8 @@ err:
return succeeded;
}
image_handle
renderer_shadow_from_mask(struct renderer *r, struct backend_base *backend,
image_handle mask, int corner_radius, struct geometry mask_size) {
image_handle renderer_shadow_from_mask(struct renderer *r, struct backend_base *backend,
image_handle mask, int corner_radius, ivec2 mask_size) {
image_handle normalized_mask_image = NULL, shadow_image = NULL,
shadow_color_pixel = NULL;
bool succeeded = false;
@ -211,7 +210,7 @@ renderer_shadow_from_mask(struct renderer *r, struct backend_base *backend,
// image, each side larger by `2 * radius` so there is space for blurring.
normalized_mask_image = backend->ops->new_image(
backend, BACKEND_IMAGE_FORMAT_MASK,
(struct geometry){mask_size.width + 2 * radius, mask_size.height + 2 * radius});
(ivec2){mask_size.width + 2 * radius, mask_size.height + 2 * radius});
if (!normalized_mask_image || !backend->ops->clear(backend, normalized_mask_image,
(struct color){0, 0, 0, 0})) {
log_error("Failed to create mask image");
@ -239,7 +238,7 @@ renderer_shadow_from_mask(struct renderer *r, struct backend_base *backend,
.border_width = 0,
.max_brightness = 1,
};
succeeded = backend->ops->blit(backend, (struct coord){radius, radius},
succeeded = backend->ops->blit(backend, (ivec2){radius, radius},
normalized_mask_image, &args);
pixman_region32_fini(&mask_args.region);
if (!succeeded) {
@ -264,8 +263,8 @@ renderer_shadow_from_mask(struct renderer *r, struct backend_base *backend,
.mask = &mask_args,
.blur_context = r->shadow_blur_context,
};
succeeded = backend->ops->blur(backend, (struct coord){0, 0},
normalized_mask_image, &args);
succeeded =
backend->ops->blur(backend, (ivec2){0, 0}, normalized_mask_image, &args);
pixman_region32_fini(&mask_args.region);
if (!succeeded) {
log_error("Failed to blur for shadow generation");
@ -276,15 +275,15 @@ renderer_shadow_from_mask(struct renderer *r, struct backend_base *backend,
succeeded = false;
shadow_image = backend->ops->new_image(
backend, BACKEND_IMAGE_FORMAT_PIXMAP,
(struct geometry){mask_size.width + 2 * radius, mask_size.height + 2 * radius});
(ivec2){mask_size.width + 2 * radius, mask_size.height + 2 * radius});
if (!shadow_image ||
!backend->ops->clear(backend, shadow_image, (struct color){0, 0, 0, 0})) {
log_error("Failed to allocate shadow image");
goto out;
}
shadow_color_pixel = backend->ops->new_image(backend, BACKEND_IMAGE_FORMAT_PIXMAP,
(struct geometry){1, 1});
shadow_color_pixel =
backend->ops->new_image(backend, BACKEND_IMAGE_FORMAT_PIXMAP, (ivec2){1, 1});
if (!shadow_color_pixel ||
!backend->ops->clear(backend, shadow_color_pixel, r->shadow_color)) {
log_error("Failed to create shadow color image");
@ -313,7 +312,7 @@ renderer_shadow_from_mask(struct renderer *r, struct backend_base *backend,
.border_width = 0,
.max_brightness = 1,
};
succeeded = backend->ops->blit(backend, (struct coord){0, 0}, shadow_image, &args);
succeeded = backend->ops->blit(backend, (ivec2){0, 0}, shadow_image, &args);
pixman_region32_fini(&mask_args.region);
out:
@ -352,7 +351,7 @@ static bool renderer_bind_shadow(struct renderer *r, struct backend_base *backen
}
w->shadow_image = renderer_shadow_from_mask(
r, backend, w->mask_image, w->corner_radius,
(struct geometry){.width = w->widthb, .height = w->heightb});
(ivec2){.width = w->widthb, .height = w->heightb});
}
if (!w->shadow_image) {
log_error("Failed to create shadow");
@ -423,7 +422,7 @@ static bool renderer_prepare_commands(struct renderer *r, struct backend_base *b
void renderer_ensure_monitor_repaint_ready(struct renderer *r, struct backend_base *backend) {
if (!r->monitor_repaint_pixel) {
r->monitor_repaint_pixel = backend->ops->new_image(
backend, BACKEND_IMAGE_FORMAT_PIXMAP, (struct geometry){1, 1});
backend, BACKEND_IMAGE_FORMAT_PIXMAP, (ivec2){1, 1});
BUG_ON(!r->monitor_repaint_pixel);
backend->ops->clear(backend, r->monitor_repaint_pixel,
(struct color){.alpha = 0.5, .red = 0.5});
@ -433,8 +432,8 @@ void renderer_ensure_monitor_repaint_ready(struct renderer *r, struct backend_ba
for (int i = 0; i < r->max_buffer_age; i++) {
r->monitor_repaint_copy[i] = backend->ops->new_image(
backend, BACKEND_IMAGE_FORMAT_PIXMAP,
(struct geometry){.width = r->canvas_size.width,
.height = r->canvas_size.height});
(ivec2){.width = r->canvas_size.width,
.height = r->canvas_size.height});
BUG_ON(!r->monitor_repaint_copy[i]);
}
}
@ -466,8 +465,8 @@ bool renderer_render(struct renderer *r, struct backend_base *backend,
// dithered present; no blur, with blur we will render areas that's just for blur
// and can't be presented;
auto layout = layout_manager_layout(lm, 0);
if (!renderer_set_root_size(
r, backend, (struct geometry){layout->size.width, layout->size.height})) {
if (!renderer_set_root_size(r, backend,
(ivec2){layout->size.width, layout->size.height})) {
log_error("Failed to allocate back image");
return false;
}
@ -499,7 +498,7 @@ bool renderer_render(struct renderer *r, struct backend_base *backend,
(unsigned)r->canvas_size.height);
pixman_region32_init(&damage_region);
pixman_region32_copy(&damage_region, &screen_region);
struct geometry blur_size = {};
ivec2 blur_size = {};
if (backend->ops->get_blur_size && blur_context) {
backend->ops->get_blur_size(blur_context, &blur_size.width, &blur_size.height);
}
@ -539,8 +538,7 @@ bool renderer_render(struct renderer *r, struct backend_base *backend,
// Restore the area of back buffer that was tainted by monitor repaint
int past_frame =
(r->frame_index + r->max_buffer_age - buffer_age) % r->max_buffer_age;
backend->ops->copy_area(backend, (struct coord){},
backend->ops->back_buffer(backend),
backend->ops->copy_area(backend, (ivec2){}, backend->ops->back_buffer(backend),
r->monitor_repaint_copy[past_frame],
&r->monitor_repaint_region[past_frame]);
}
@ -553,7 +551,7 @@ bool renderer_render(struct renderer *r, struct backend_base *backend,
if (monitor_repaint) {
// Keep a copy of un-tainted back image
backend->ops->copy_area(backend, (struct coord){},
backend->ops->copy_area(backend, (ivec2){},
r->monitor_repaint_copy[r->frame_index],
r->back_image, &damage_region);
pixman_region32_copy(&r->monitor_repaint_region[r->frame_index], &damage_region);
@ -568,11 +566,11 @@ bool renderer_render(struct renderer *r, struct backend_base *backend,
.mask = &mask,
};
log_trace("Blit for monitor repaint");
backend->ops->blit(backend, (struct coord){}, r->back_image, &blit);
backend->ops->blit(backend, (ivec2){}, r->back_image, &blit);
}
if (backend->ops->present) {
backend->ops->copy_area_quantize(backend, (struct coord){},
backend->ops->copy_area_quantize(backend, (ivec2){},
backend->ops->back_buffer(backend),
r->back_image, &damage_region);
backend->ops->present(backend);

View File

@ -31,35 +31,51 @@ struct color {
typedef uint32_t opacity_t;
typedef struct geometry {
int width;
int height;
} geometry_t;
typedef struct vec2 {
union {
double x;
double width;
};
union {
double y;
double height;
};
} vec2;
typedef struct coord {
int x, y;
} coord_t;
typedef struct ivec2 {
union {
int x;
int width;
};
union {
int y;
int height;
};
} ivec2;
static inline struct coord coord_add(struct coord a, struct coord b) {
return (struct coord){
static inline ivec2 ivec2_add(ivec2 a, ivec2 b) {
return (ivec2){
.x = a.x + b.x,
.y = a.y + b.y,
};
}
static inline struct coord coord_sub(struct coord a, struct coord b) {
return (struct coord){
static inline ivec2 ivec2_sub(ivec2 a, ivec2 b) {
return (ivec2){
.x = a.x - b.x,
.y = a.y - b.y,
};
}
static inline bool coord_eq(struct coord a, struct coord b) {
static inline bool ivec2_eq(ivec2 a, ivec2 b) {
return a.x == b.x && a.y == b.y;
}
static inline struct coord coord_neg(struct coord a) {
return (struct coord){.x = -a.x, .y = -a.y};
static inline ivec2 ivec2_neg(ivec2 a) {
return (ivec2){
.x = -a.x,
.y = -a.y,
};
}
#define MARGIN_INIT \