From: Ray Strode Date: Thu, 20 Aug 2009 03:55:43 +0000 (-0400) Subject: [libply] Add new region class X-Git-Tag: 0.8.0~188^2~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b032e6d4f4acf1ad371d4a810ef8362ebcf4d264;p=thirdparty%2Fplymouth.git [libply] Add new region class Sometimes it's necessary to deal with a disjoint set of rectangles together. One big example is when keeping track of which parts of the screen have changed. Another example would be for non-rectangular clip masks. This commit adds a new region class to simplify the handling of these types of cases. --- diff --git a/src/libply/Makefile.am b/src/libply/Makefile.am index da145755..f87bf25d 100644 --- a/src/libply/Makefile.am +++ b/src/libply/Makefile.am @@ -24,6 +24,7 @@ libply_HEADERS = \ ply-key-file.h \ ply-progress.h \ ply-rectangle.h \ + ply-region.h \ ply-terminal-session.h \ ply-trigger.h \ ply-utils.h @@ -46,6 +47,7 @@ libply_la_SOURCES = ply-event-loop.c \ ply-key-file.c \ ply-progress.c \ ply-rectangle.c \ + ply-region.c \ ply-terminal-session.c \ ply-trigger.c \ ply-utils.c diff --git a/src/libply/ply-region.c b/src/libply/ply-region.c new file mode 100644 index 00000000..ec6ca5d7 --- /dev/null +++ b/src/libply/ply-region.c @@ -0,0 +1,390 @@ +/* ply-region.c + * + * Copyright (C) 2009 Red Hat, Inc. + * + * Based in part on some work by: + * Copyright (C) 2009 Charlie Brej + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written by: Charlie Brej + * Ray Strode + */ +#include "config.h" +#include "ply-region.h" + +#include +#include + +#include "ply-list.h" +#include "ply-rectangle.h" + +struct _ply_region +{ + ply_list_t *rectangle_list; +}; + +ply_region_t * +ply_region_new (void) +{ + ply_region_t *region; + + region = calloc (1, sizeof (ply_region_t)); + + region->rectangle_list = ply_list_new (); + + return region; +} + +void +ply_region_clear (ply_region_t *region) +{ + ply_list_node_t *node; + + node = ply_list_get_first_node (region->rectangle_list); + while (node != NULL) + { + ply_list_node_t *next_node; + ply_rectangle_t *rectangle; + + rectangle = (ply_rectangle_t *) ply_list_node_get_data (node); + + next_node = ply_list_get_next_node (region->rectangle_list, node); + + free (rectangle); + ply_list_remove_node (region->rectangle_list, node); + + node = next_node; + } +} + +void +ply_region_free (ply_region_t *region) +{ + + ply_region_clear (region); + ply_list_free (region->rectangle_list); + free (region); +} + +static ply_rectangle_t * +copy_rectangle (ply_rectangle_t *rectangle) +{ + ply_rectangle_t *new_rectangle; + + new_rectangle = malloc (sizeof (*rectangle)); + *new_rectangle = *rectangle; + + return new_rectangle; +} + +static void +merge_rectangle_with_sub_list (ply_region_t *region, + ply_rectangle_t *new_area, + ply_list_node_t *node) +{ + + if (ply_rectangle_is_empty (new_area)) + return; + + while (node != NULL) + { + ply_list_node_t *next_node; + ply_rectangle_t *old_area; + ply_rectangle_overlap_t overlap; + + old_area = (ply_rectangle_t *) ply_list_node_get_data (node); + + next_node = ply_list_get_next_node (region->rectangle_list, node); + + overlap = ply_rectangle_find_overlap (old_area, new_area); + + switch (overlap) + { + /* NNNN The new rectangle and node rectangle don't touch, + * NNNN OOOO so let's move on to the next one. + * OOOO + */ + case PLY_RECTANGLE_OVERLAP_NONE: + break; + + /* NNNNN We need to split the new rectangle into + * NNOOOOO two rectangles: The top row of Ns and + * NNOOOOO the left side of Ns. + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_TOP_AND_LEFT_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + rectangle->y = old_area->y; + rectangle->width = old_area->x - new_area->x; + rectangle->height = (new_area->y + new_area->height) - old_area->y; + + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->height = old_area->y - new_area->y; + } + break; + + /* NNNNN We need to split the new rectangle into + * OOOOONN two rectangles: The top row of Ns and + * OOOOONN the right side of Ns. + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_TOP_AND_RIGHT_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + rectangle->x = new_area->x + old_area->width; + rectangle->y = old_area->y; + rectangle->width = (old_area->x + new_area->width) - (old_area->x + old_area->width); + rectangle->height = (new_area->y + new_area->height) - old_area->y; + + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->height = old_area->y - new_area->y; + } + break; + + /* NNNNNNN We need to trim out the part of + * NOOOOON old rectangle that overlaps the new + * NOOOOON rectangle by shrinking and moving it + * OOOOO and then we need to add the new rectangle. + */ + case PLY_RECTANGLE_OVERLAP_TOP_AND_SIDE_EDGES: + { + old_area->height = (old_area->y + old_area->height) + - (new_area->y + new_area->height); + old_area->y = new_area->y + new_area->height; + } + + /* NNN We only care about the top row of Ns, + * ONNNO everything below that is already handled by + * ONNNO the old rectangle. + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_TOP_EDGE: + new_area->height = old_area->y - new_area->y; + break; + + /* OOOOO We need to split the new rectangle into + * NNOOOOO two rectangles: The left side of Ns and + * NNOOOOO the bottom row of Ns. + * NNOOOOO + * NNNNN + */ + case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_LEFT_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + + rectangle->y = old_area->y; + rectangle->width = old_area->x - new_area->x; + rectangle->height = (old_area->y + old_area->height) - new_area->y; + + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); + new_area->width = new_area->width; + new_area->y = old_area->y + old_area->height; + } + break; + + /* OOOOO We need to split the new rectangle into + * OOOOONN two rectangles: The right side of Ns and + * OOOOONN the bottom row of Ns. + * OOOOONN + * NNNNN + */ + case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_RIGHT_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + + rectangle->x = old_area->x + old_area->width; + rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); + rectangle->height = (old_area->y + old_area->height) - new_area->y; + + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); + new_area->y = old_area->y + old_area->height; + } + break; + + /* OOOOO We need to trim out the part of + * NOOOOON old rectangle that overlaps the new + * NOOOOON rectangle by shrinking it + * NNNNNNN and then we need to add the new rectangle. + */ + case PLY_RECTANGLE_OVERLAP_BOTTOM_AND_SIDE_EDGES: + { + old_area->height = (new_area->y + new_area->height) + - (old_area->y + old_area->height); + } + break; + + /* OOOOO We only care about the bottom row of Ns, + * ONNNO everything above that is already handled by + * ONNNO the old rectangle. + * NNN + */ + case PLY_RECTANGLE_OVERLAP_BOTTOM_EDGE: + { + new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); + new_area->y = old_area->y + old_area->height; + } + break; + + /* NNNN We need to trim out the part of + * NNNNO old rectangle that overlaps the new + * NNNNO rectangle by shrinking it and moving it + * NNNN and then we need to add the new rectangle. + */ + case PLY_RECTANGLE_OVERLAP_TOP_LEFT_AND_BOTTOM_EDGES: + { + old_area->width = (old_area->x + old_area->width) + - (new_area->x + new_area->width); + old_area->x = new_area->x + new_area->width; + } + break; + + /* NNNN We need to trim out the part of + * ONNNN old rectangle that overlaps the new + * ONNNN rectangle by shrinking it and then we + * NNNN need to add the new rectangle. + */ + case PLY_RECTANGLE_OVERLAP_TOP_RIGHT_AND_BOTTOM_EDGES: + old_area->width = new_area->x - old_area->x; + break; + + /* NNNNNNN The old rectangle is completely inside the new rectangle + * NOOOOON so replace the old rectangle with the new rectangle. + * NOOOOON + * NNNNNNN + */ + case PLY_RECTANGLE_OVERLAP_ALL_EDGES: + free (old_area); + ply_list_remove_node (region->rectangle_list, node); + break; + + /* NNN We need to split the new rectangle into + * ONNNO two rectangles: the top and bottom row of Ns + * ONNNO + * NNN + */ + case PLY_RECTANGLE_OVERLAP_TOP_AND_BOTTOM_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + rectangle->y = old_area->y + old_area->height; + rectangle->width = new_area->width; + rectangle->height = (new_area->y + new_area->height) - (old_area->y + old_area->height); + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->height = old_area->y - new_area->y; + } + break; + + /* OOOOO We only care about the side row of Ns, + * NNNNOO everything rigth of that is already handled by + * NNNNOO the old rectangle. + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_LEFT_EDGE: + new_area->width = old_area->x - new_area->x; + break; + + /* OOOOO We only care about the side row of Ns, + * NNNNNN everything left of that is already handled by + * NNNNNN the old rectangle. + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_RIGHT_EDGE: + { + new_area->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); + new_area->x = old_area->x + old_area->width; + } + break; + + /* OOOOO We need to split the new rectangle into + * NNNNNNN two rectangles: the side columns of Ns + * NNNNNNN + * OOOOO + */ + case PLY_RECTANGLE_OVERLAP_SIDE_EDGES: + { + ply_rectangle_t *rectangle; + + rectangle = copy_rectangle (new_area); + + rectangle->x = old_area->x + old_area->width; + rectangle->width = (new_area->x + new_area->width) - (old_area->x + old_area->width); + + merge_rectangle_with_sub_list (region, rectangle, node); + + new_area->width = old_area->x - new_area->x; + } + break; + + /* OOOOOOO The new rectangle is completely inside an old rectangle + * ONNNNNO so return early without adding the new rectangle. + * ONNNNNO + * OOOOOOO + */ + case PLY_RECTANGLE_OVERLAP_NO_EDGES: + free (new_area); + return; + + } + + node = next_node; + } + + ply_list_append_data (region->rectangle_list, new_area); +} + +void +ply_region_add_rectangle (ply_region_t *region, + ply_rectangle_t *rectangle) +{ + ply_list_node_t *first_node; + ply_rectangle_t *rectangle_copy; + + assert (region != NULL); + assert (rectangle != NULL); + + first_node = ply_list_get_first_node (region->rectangle_list); + + rectangle_copy = copy_rectangle (rectangle); + merge_rectangle_with_sub_list (region, + rectangle_copy, + first_node); +} + +ply_list_t * +ply_region_get_rectangle_list (ply_region_t *region) +{ + return region->rectangle_list; +} + +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */ diff --git a/src/libply/ply-region.h b/src/libply/ply-region.h new file mode 100644 index 00000000..ee6e992f --- /dev/null +++ b/src/libply/ply-region.h @@ -0,0 +1,47 @@ +/* ply-region.h + * + * Copyright (C) 2009 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + * + * Written By: Ray Strode + */ +#ifndef PLY_REGION_H +#define PLY_REGION_H + +#include +#include + +#include "ply-list.h" +#include "ply-rectangle.h" +#include "ply-utils.h" + +typedef struct _ply_region ply_region_t; + +#ifndef PLY_HIDE_FUNCTION_DECLARATIONS +ply_region_t *ply_region_new (void); +void ply_region_free (ply_region_t *region); +void ply_region_add_rectangle (ply_region_t *region, + ply_rectangle_t *rectangle); +void ply_region_clear (ply_region_t *region); +ply_list_t *ply_region_get_rectangle_list (ply_region_t *region); + +bool ply_region_is_empty (ply_region_t *region); + +#endif + +#endif /* PLY_REGION_H */ +/* vim: set ts=4 sw=4 expandtab autoindent cindent cino={.5s,(0: */