/** Returns the topmost non-layer group from the descendants of group which is at point p, or NULL if none. Recurses into layers but not into groups. */ SPItem* find_group_at_point(unsigned int dkey, SPGroup *group, Geom::Point const p) { SPItem *seen = 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 (SP_IS_GROUP(o) && SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER) { SPItem *newseen = find_group_at_point(dkey, SP_GROUP(o), p); if (newseen) { seen = newseen; } } if (SP_IS_GROUP(o) && SP_GROUP(o)->effectiveLayerMode(dkey) != SPGroup::LAYER ) { SPItem *child = SP_ITEM(o); NRArenaItem *arenaitem = sp_item_get_arenaitem(child, dkey); // seen remembers the last (topmost) of groups pickable at this point if (arenaitem && nr_arena_item_invoke_pick(arenaitem, p, delta, 1) != NULL) { seen = child; } } } return seen; }
/** 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; }
/** 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; }
/** * Process a GdkPixbuf, according to which areas have been * obscured in the GUI. */ Glib::RefPtr<Gdk::Pixbuf> Tracer::sioxProcessImage(SPImage *img, Glib::RefPtr<Gdk::Pixbuf>origPixbuf) { if (!sioxEnabled) return origPixbuf; if (origPixbuf == lastOrigPixbuf) return lastSioxPixbuf; //g_message("siox: start"); //Convert from gdk, so a format we know. By design, the pixel //format in PackedPixelMap is identical to what is needed by SIOX SioxImage simage(origPixbuf->gobj()); SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (!desktop) { g_warning(_("Trace: No active desktop")); return Glib::RefPtr<Gdk::Pixbuf>(NULL); } Inkscape::MessageStack *msgStack = sp_desktop_message_stack(desktop); Inkscape::Selection *sel = sp_desktop_selection(desktop); if (!sel) { char *msg = _("Select an <b>image</b> to trace"); msgStack->flash(Inkscape::ERROR_MESSAGE, msg); //g_warning(msg); return Glib::RefPtr<Gdk::Pixbuf>(NULL); } NRArenaItem *aImg = sp_item_get_arenaitem(img, desktop->dkey); //g_message("img: %d %d %d %d\n", aImg->bbox.x0, aImg->bbox.y0, // aImg->bbox.x1, aImg->bbox.y1); double width = (double)(aImg->bbox.x1 - aImg->bbox.x0); double height = (double)(aImg->bbox.y1 - aImg->bbox.y0); double iwidth = (double)simage.getWidth(); double iheight = (double)simage.getHeight(); double iwscale = width / iwidth; double ihscale = height / iheight; std::vector<NRArenaItem *> arenaItems; std::vector<SPShape *>::iterator iter; for (iter = sioxShapes.begin() ; iter!=sioxShapes.end() ; iter++) { SPItem *item = *iter; NRArenaItem *aItem = sp_item_get_arenaitem(item, desktop->dkey); arenaItems.push_back(aItem); } //g_message("%d arena items\n", arenaItems.size()); //PackedPixelMap *dumpMap = PackedPixelMapCreate( // simage.getWidth(), simage.getHeight()); //g_message("siox: start selection"); for (int row=0 ; row<iheight ; row++) { double ypos = ((double)aImg->bbox.y0) + ihscale * (double) row; for (int col=0 ; col<simage.getWidth() ; col++) { //Get absolute X,Y position double xpos = ((double)aImg->bbox.x0) + iwscale * (double)col; Geom::Point point(xpos, ypos); point *= *aImg->transform; //point *= imgMat; //point = desktop->doc2dt(point); //g_message("x:%f y:%f\n", point[0], point[1]); bool weHaveAHit = false; std::vector<NRArenaItem *>::iterator aIter; for (aIter = arenaItems.begin() ; aIter!=arenaItems.end() ; aIter++) { NRArenaItem *arenaItem = *aIter; NRArenaItemClass *arenaClass = (NRArenaItemClass *) NR_OBJECT_GET_CLASS (arenaItem); if (arenaClass->pick(arenaItem, point, 1.0f, 1)) { weHaveAHit = true; break; } } if (weHaveAHit) { //g_message("hit!\n"); //dumpMap->setPixelLong(dumpMap, col, row, 0L); simage.setConfidence(col, row, Siox::UNKNOWN_REGION_CONFIDENCE); } else { //g_message("miss!\n"); //dumpMap->setPixelLong(dumpMap, col, row, // simage.getPixel(col, row)); simage.setConfidence(col, row, Siox::CERTAIN_BACKGROUND_CONFIDENCE); } } } //g_message("siox: selection done"); //dumpMap->writePPM(dumpMap, "siox1.ppm"); //dumpMap->destroy(dumpMap); //## ok we have our pixel buf TraceSioxObserver observer(this); Siox sengine(&observer); SioxImage result = sengine.extractForeground(simage, 0xffffff); if (!result.isValid()) { g_warning(_("Invalid SIOX result")); return Glib::RefPtr<Gdk::Pixbuf>(NULL); } //result.writePPM("siox2.ppm"); /* Free Arena and ArenaItem */ /* std::vector<NRArenaItem *>::iterator aIter; for (aIter = arenaItems.begin() ; aIter!=arenaItems.end() ; aIter++) { NRArenaItem *arenaItem = *aIter; nr_arena_item_unref(arenaItem); } nr_object_unref((NRObject *) arena); */ Glib::RefPtr<Gdk::Pixbuf> newPixbuf = Glib::wrap(result.getGdkPixbuf()); //g_message("siox: done"); lastSioxPixbuf = newPixbuf; return newPixbuf; }