diff options
Diffstat (limited to 'gsk/gl/ninesliceprivate.h')
-rw-r--r-- | gsk/gl/ninesliceprivate.h | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/gsk/gl/ninesliceprivate.h b/gsk/gl/ninesliceprivate.h new file mode 100644 index 0000000000..1ad905929d --- /dev/null +++ b/gsk/gl/ninesliceprivate.h @@ -0,0 +1,310 @@ +/* ninesliceprivate.h + * + * Copyright 2017 Timm Bäder <mail@baedert.org> + * Copyright 2021 Christian Hergert <chergert@redhat.com> + * + * This library 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 2.1 of the License, or (at your option) any later version. + * + * This library 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 Lesser General Public + * License along with this program. If not, see <http://www.gnu.org/licenses/>. + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef __NINE_SLICE_PRIVATE_H__ +#define __NINE_SLICE_PRIVATE_H__ + +#include "gskgltextureprivate.h" + +#if 0 +# define DEBUG_NINE_SLICE +#endif + +G_BEGIN_DECLS + +enum { + NINE_SLICE_TOP_LEFT = 0, + NINE_SLICE_TOP_CENTER = 1, + NINE_SLICE_TOP_RIGHT = 2, + NINE_SLICE_LEFT_CENTER = 3, + NINE_SLICE_CENTER = 4, + NINE_SLICE_RIGHT_CENTER = 5, + NINE_SLICE_BOTTOM_LEFT = 6, + NINE_SLICE_BOTTOM_CENTER = 7, + NINE_SLICE_BOTTOM_RIGHT = 8, +}; + +static inline bool G_GNUC_PURE +nine_slice_is_visible (const GskGLTextureNineSlice *slice) +{ + return slice->rect.width > 0 && slice->rect.height > 0; +} + +static inline void +nine_slice_rounded_rect (GskGLTextureNineSlice *slices, + const GskRoundedRect *rect) +{ + const graphene_point_t *origin = &rect->bounds.origin; + const graphene_size_t *size = &rect->bounds.size; + int top_height = ceilf (MAX (rect->corner[GSK_CORNER_TOP_LEFT].height, + rect->corner[GSK_CORNER_TOP_RIGHT].height)); + int bottom_height = ceilf (MAX (rect->corner[GSK_CORNER_BOTTOM_LEFT].height, + rect->corner[GSK_CORNER_BOTTOM_RIGHT].height)); + int right_width = ceilf (MAX (rect->corner[GSK_CORNER_TOP_RIGHT].width, + rect->corner[GSK_CORNER_BOTTOM_RIGHT].width)); + int left_width = ceilf (MAX (rect->corner[GSK_CORNER_TOP_LEFT].width, + rect->corner[GSK_CORNER_BOTTOM_LEFT].width)); + + /* Top left */ + slices[0].rect.x = origin->x; + slices[0].rect.y = origin->y; + slices[0].rect.width = left_width; + slices[0].rect.height = top_height; + + /* Top center */ + slices[1].rect.x = origin->x + size->width / 2.0 - 0.5; + slices[1].rect.y = origin->y; + slices[1].rect.width = 1; + slices[1].rect.height = top_height; + + /* Top right */ + slices[2].rect.x = origin->x + size->width - right_width; + slices[2].rect.y = origin->y; + slices[2].rect.width = right_width; + slices[2].rect.height = top_height; + + /* Left center */ + slices[3].rect.x = origin->x; + slices[3].rect.y = origin->y + size->height / 2; + slices[3].rect.width = left_width; + slices[3].rect.height = 1; + + /* center */ + slices[4].rect.x = origin->x + size->width / 2.0 - 0.5; + slices[4].rect.y = origin->y + size->height / 2.0 - 0.5; + slices[4].rect.width = 1; + slices[4].rect.height = 1; + + /* Right center */ + slices[5].rect.x = origin->x + size->width - right_width; + slices[5].rect.y = origin->y + (size->height / 2.0) - 0.5; + slices[5].rect.width = right_width; + slices[5].rect.height = 1; + + /* Bottom Left */ + slices[6].rect.x = origin->x; + slices[6].rect.y = origin->y + size->height - bottom_height; + slices[6].rect.width = left_width; + slices[6].rect.height = bottom_height; + + /* Bottom center */ + slices[7].rect.x = origin->x + (size->width / 2.0) - 0.5; + slices[7].rect.y = origin->y + size->height - bottom_height; + slices[7].rect.width = 1; + slices[7].rect.height = bottom_height; + + /* Bottom right */ + slices[8].rect.x = origin->x + size->width - right_width; + slices[8].rect.y = origin->y + size->height - bottom_height; + slices[8].rect.width = right_width; + slices[8].rect.height = bottom_height; + +#ifdef DEBUG_NINE_SLICE + /* These only hold true when the values from ceilf() above + * are greater than one. Otherwise they fail, like will happen + * with the node editor viewing the textures zoomed out. + */ + if (size->width > 1) + g_assert_cmpfloat (size->width, >=, left_width + right_width); + if (size->height > 1) + g_assert_cmpfloat (size->height, >=, top_height + bottom_height); +#endif +} + +static inline void +nine_slice_to_texture_coords (GskGLTextureNineSlice *slices, + int texture_width, + int texture_height) +{ + float fw = texture_width; + float fh = texture_height; + + for (guint i = 0; i < 9; i++) + { + GskGLTextureNineSlice *slice = &slices[i]; + + slice->area.x = slice->rect.x / fw; + slice->area.y = 1.0 - ((slice->rect.y + slice->rect.height) / fh); + slice->area.x2 = ((slice->rect.x + slice->rect.width) / fw); + slice->area.y2 = (1.0 - (slice->rect.y / fh)); + +#ifdef DEBUG_NINE_SLICE + g_assert_cmpfloat (slice->area.x, >=, 0); + g_assert_cmpfloat (slice->area.x, <=, 1); + g_assert_cmpfloat (slice->area.y, >=, 0); + g_assert_cmpfloat (slice->area.y, <=, 1); + g_assert_cmpfloat (slice->area.x2, >, slice->area.x); + g_assert_cmpfloat (slice->area.y2, >, slice->area.y); +#endif + } +} + +static inline void +nine_slice_grow (GskGLTextureNineSlice *slices, + int amount_x, + int amount_y) +{ + if (amount_x == 0 && amount_y == 0) + return; + + /* top left */ + slices[0].rect.x -= amount_x; + slices[0].rect.y -= amount_y; + if (amount_x > slices[0].rect.width) + slices[0].rect.width += amount_x * 2; + else + slices[0].rect.width += amount_x; + + if (amount_y > slices[0].rect.height) + slices[0].rect.height += amount_y * 2; + else + slices[0].rect.height += amount_y; + + + /* Top center */ + slices[1].rect.y -= amount_y; + if (amount_y > slices[1].rect.height) + slices[1].rect.height += amount_y * 2; + else + slices[1].rect.height += amount_y; + + /* top right */ + slices[2].rect.y -= amount_y; + if (amount_x > slices[2].rect.width) + { + slices[2].rect.x -= amount_x; + slices[2].rect.width += amount_x * 2; + } + else + { + slices[2].rect.width += amount_x; + } + + if (amount_y > slices[2].rect.height) + slices[2].rect.height += amount_y * 2; + else + slices[2].rect.height += amount_y; + + + + slices[3].rect.x -= amount_x; + if (amount_x > slices[3].rect.width) + slices[3].rect.width += amount_x * 2; + else + slices[3].rect.width += amount_x; + + /* Leave center alone */ + + if (amount_x > slices[5].rect.width) + { + slices[5].rect.x -= amount_x; + slices[5].rect.width += amount_x * 2; + } + else + { + slices[5].rect.width += amount_x; + } + + + /* Bottom left */ + slices[6].rect.x -= amount_x; + if (amount_x > slices[6].rect.width) + { + slices[6].rect.width += amount_x * 2; + } + else + { + slices[6].rect.width += amount_x; + } + + if (amount_y > slices[6].rect.height) + { + slices[6].rect.y -= amount_y; + slices[6].rect.height += amount_y * 2; + } + else + { + slices[6].rect.height += amount_y; + } + + + /* Bottom center */ + if (amount_y > slices[7].rect.height) + { + slices[7].rect.y -= amount_y; + slices[7].rect.height += amount_y * 2; + } + else + { + slices[7].rect.height += amount_y; + } + + if (amount_x > slices[8].rect.width) + { + slices[8].rect.x -= amount_x; + slices[8].rect.width += amount_x * 2; + } + else + { + slices[8].rect.width += amount_x; + } + + if (amount_y > slices[8].rect.height) + { + slices[8].rect.y -= amount_y; + slices[8].rect.height += amount_y * 2; + } + else + { + slices[8].rect.height += amount_y; + } + +#ifdef DEBUG_NINE_SLICE + /* These cannot be relied on in all cases right now, specifically + * when viewing data zoomed out. + */ + for (guint i = 0; i < 9; i ++) + { + g_assert_cmpint (slices[i].rect.x, >=, 0); + g_assert_cmpint (slices[i].rect.y, >=, 0); + g_assert_cmpint (slices[i].rect.width, >=, 0); + g_assert_cmpint (slices[i].rect.height, >=, 0); + } + + /* Rows don't overlap */ + for (guint i = 0; i < 3; i++) + { + int lhs = slices[i * 3 + 0].rect.x + slices[i * 3 + 0].rect.width; + int rhs = slices[i * 3 + 1].rect.x; + + /* Ignore the case where we are scaled out and the + * positioning is degenerate, such as from node-editor. + */ + if (rhs > 1) + g_assert_cmpint (lhs, <, rhs); + } +#endif + +} + +G_END_DECLS + +#endif /* __NINE_SLICE_PRIVATE_H__ */ |