/** Returns the bottommost item from the list which is at the point, or NULL if none. */ SPItem* sp_document_item_from_list_at_point_bottom(unsigned int dkey, SPGroup *group, GSList const *list, Geom::Point const p, bool take_insensitive) { g_return_val_if_fail(group, NULL); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gdouble delta = prefs->getDouble("/options/cursortolerance/value", 1.0); for (SPObject *o = sp_object_first_child(SP_OBJECT(group)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) { if (!SP_IS_ITEM(o)) continue; SPItem *item = SP_ITEM(o); NRArenaItem *arenaitem = sp_item_get_arenaitem(item, dkey); if (arenaitem && nr_arena_item_invoke_pick(arenaitem, p, delta, 1) != NULL && (take_insensitive || item->isVisibleAndUnlocked(dkey))) { if (g_slist_find((GSList *) list, item) != NULL) return item; } if (SP_IS_GROUP(o)) { SPItem *found = sp_document_item_from_list_at_point_bottom(dkey, SP_GROUP(o), list, p, take_insensitive); if (found) return found; } } return NULL; }
static GSList *find_items_in_area(GSList *s, SPGroup *group, unsigned int dkey, Geom::Rect const &area, bool (*test)(Geom::Rect const &, Geom::Rect const &), bool take_insensitive = false) { g_return_val_if_fail(SP_IS_GROUP(group), s); for (SPObject *o = sp_object_first_child(SP_OBJECT(group)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) { if (!SP_IS_ITEM(o)) { continue; } if (SP_IS_GROUP(o) && SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER ) { s = find_items_in_area(s, SP_GROUP(o), dkey, area, test); } else { SPItem *child = SP_ITEM(o); Geom::OptRect box = sp_item_bbox_desktop(child); if ( box && test(area, *box) && (take_insensitive || child->isVisibleAndUnlocked(dkey))) { s = g_slist_append(s, child); } } } return s; }
/** Returns the topmost (in z-order) item from the descendants of group (recursively) which is at the point p, or NULL if none. Honors into_groups on whether to recurse into non-layer groups or not. Honors take_insensitive on whether to return insensitive items. If upto != NULL, then if item upto is encountered (at any level), stops searching upwards in z-order and returns what it has found so far (i.e. the found item is guaranteed to be lower than upto). */ SPItem* find_item_at_point(unsigned int dkey, SPGroup *group, Geom::Point const p, gboolean into_groups, bool take_insensitive = false, SPItem *upto = NULL) { SPItem *seen = NULL, *newseen = NULL; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gdouble delta = prefs->getDouble("/options/cursortolerance/value", 1.0); for (SPObject *o = sp_object_first_child(SP_OBJECT(group)) ; o != NULL ; o = SP_OBJECT_NEXT(o) ) { if (!SP_IS_ITEM(o)) continue; if (upto && SP_ITEM(o) == upto) break; if (SP_IS_GROUP(o) && (SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups)) { // if nothing found yet, recurse into the group newseen = find_item_at_point(dkey, SP_GROUP(o), p, into_groups, take_insensitive, upto); if (newseen) { seen = newseen; newseen = NULL; } if (item_is_in_group(upto, SP_GROUP(o))) break; } else { SPItem *child = SP_ITEM(o); NRArenaItem *arenaitem = sp_item_get_arenaitem(child, dkey); // seen remembers the last (topmost) of items pickable at this point if (arenaitem && nr_arena_item_invoke_pick(arenaitem, p, delta, 1) != NULL && (take_insensitive || child->isVisibleAndUnlocked(dkey))) { seen = child; } } } return seen; }