spray-context.cpp revision ded6af6ae9b11c88a4257b43744ef89ccbf13dfb
#define __SP_SPRAY_CONTEXT_C__
/*
* Spray Tool
*
* Authors:
* Pierre-Antoine MARC
* Pierre CACLIN
* Aurel-Aimé MARMION
* Julien LERAY
* Benoît LAVORATA
* Vincent MONTAGNE
* Pierre BARBRY-BLOT
*
* Copyright (C) 2009 authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include "config.h"
#include <gdk/gdkkeysyms.h>
#include <numeric>
#include "display/canvas-bpath.h"
#include "macros.h"
#include "document.h"
#include "selection.h"
#include "desktop.h"
#include "desktop-events.h"
#include "desktop-handles.h"
#include "unistd.h"
#include "desktop-style.h"
#include "message-context.h"
#include "pixmaps/cursor-spray.xpm"
#include "pixmaps/cursor-spray-move.xpm"
#include "pixmaps/cursor-thin.xpm"
#include "pixmaps/cursor-thicken.xpm"
#include "pixmaps/cursor-attract.xpm"
#include "pixmaps/cursor-repel.xpm"
#include "pixmaps/cursor-push.xpm"
#include "pixmaps/cursor-roughen.xpm"
#include "pixmaps/cursor-color.xpm"
#include <boost/optional.hpp>
#include "libnr/nr-matrix-ops.h"
#include "libnr/nr-scale-translate-ops.h"
#include "context-fns.h"
#include "sp-item.h"
#include "inkscape.h"
#include "color.h"
#include "svg/svg-color.h"
#include "splivarot.h"
#include "sp-item-group.h"
#include "sp-shape.h"
#include "sp-path.h"
#include "path-chemistry.h"
#include "sp-gradient.h"
#include "sp-stop.h"
#include "sp-stop-fns.h"
#include "sp-gradient-reference.h"
#include "sp-linear-gradient.h"
#include "sp-radial-gradient.h"
#include "gradient-chemistry.h"
#include "sp-text.h"
#include "sp-flowtext.h"
#include "display/canvas-bpath.h"
#include "display/canvas-arena.h"
#include "preferences.h"
#include "style.h"
#include "box3d.h"
#include "sp-item-transform.h"
#include "filter-chemistry.h"
#include "sp-gaussian-blur-fns.h"
#include "sp-gaussian-blur.h"
#include "spray-context.h"
#include "ui/dialog/dialog-manager.h"
#include <iostream>
using namespace std;
#define DDC_RED_RGBA 0xff0000ff
#define DYNA_MIN_WIDTH 1.0e-6
static SPEventContextClass *parent_class = 0;
// The following code implements NormalDistribution wich is used for the density of the spray
/*
RAND is a macro which returns a pseudo-random numbers from a uniform
distribution on the interval [0 1]
*/
/*
TWOPI = 2.0*pi
*/
/*
RANDN is a macro which returns a pseudo-random numbers from a normal
distribution with mean zero and standard deviation one. This macro uses Box
Muller's algorithm
*/
{
/*
This function returns a pseudo-random numbers from a normal distribution with
mean equal at mu and standard deviation equal at sigma > 0
*/
}
//Fin de la création de NormalDistribution
{
if (!type) {
sizeof(SPSprayContextClass),
sizeof(SPSprayContext),
4,
NULL, /* value_table */
};
}
return type;
}
{
}
/*Method to rotate items*/
void sp_spray_rotate_rel(Geom::Point c,SPDesktop */*desktop*/,SPItem *item, Geom::Rotate const &rotation)
{
// Rotate item.
// Use each item's own transform writer, consistent with sp_selection_apply_affine()
// Restore the center position (it's changed because the bbox center changed)
if (item->isCenterSet()) {
item->updateRepr();
}
}
/*Method to scale items*/
void sp_spray_scale_rel(Geom::Point c, SPDesktop */*desktop*/, SPItem *item, Geom::Scale const &scale)
{
}
{
/* attributes */
tc->is_dilating = false;
tc->has_dilated = false;
}
{
if (tc->dilate_area) {
}
if (tc->_message_context) {
delete tc->_message_context;
}
}
{
return (mode == SPRAY_MODE_COPY ||
mode == SPRAY_MODE_CLONE ||
mode == SPRAY_MODE_SINGLE_PATH ||
mode == SPRAY_OPTION);
}
{
sel_message = g_strdup_printf(ngettext("<b>%i</b> object selected","<b>%i</b> objects selected",num), num);
} else {
}
case SPRAY_MODE_COPY:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or scroll to spray <b>copies</b> of the initial selection"), sel_message);
break;
case SPRAY_MODE_CLONE:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or scroll to spray <b>clones</b> of the initial selection"), sel_message);
break;
case SPRAY_MODE_SINGLE_PATH:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Drag, click or scroll to spray in a <b>single path</b> of the initial selection"), sel_message);
break;
case SPRAY_OPTION:
tc->_message_context->setF(Inkscape::NORMAL_MESSAGE, _("%s. Modify <b>spray</b> options"), sel_message);
break;
}
}
{
{
/* TODO: have a look at sp_dyna_draw_context_setup where the same is done.. generalize? at least make it an arcto! */
const double C1 = 0.552;
c->moveto(-1,0);
c->closepath();
c->unref();
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(tc->dilate_area), 0xff9900ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
}
tc->is_drawing = false;
;
ec->enableSelectionCue();
}
ec->enableGrDrag();
}
}
{
if (path == "width") {
} else if (path == "mode") {
sp_spray_update_cursor(tc, false);
} else if (path == "distribution") {
} else if (path == "population") {
} else if (path == "tilt") {
} else if (path == "ratio") {
} else if (path == "force") {
} else if (path == "rot_min") {
} else if (path == "rot_max") {
} else if (path == "scale_min") {
} else if (path == "scale_max") {
} else if (path == "mean") {
} else if (path == "standard_deviation") {
} else if (path == "usepressure") {
} else if (path == "doh") {
} else if (path == "dos") {
} else if (path == "dol") {
} else if (path == "doo") {
}
}
{
else
}
{
}
{
if (force > 3) {
}
}
{
}
{
return tc->standard_deviation;
}
{
}
{
}
{
return tc->standard_deviation;
}
/* Method to handle the distribution of the items */
void random_position( double &r, double &p, double &a, double &s, int choix)
{
if (choix == 0) // Mode 1 : uniform repartition
{
}
{
double r_temp =-1;
{
}
// generates a number following a normal distribution
r=r_temp;
/* if (r_temp<=0) r=0;
else
{
if (r_temp>1) r=1;
else r = r_temp;
}*/
}
}
double radius,
double /*force*/,
double population,
double &scale,
double scale_min,
double scale_max,
bool /*reverse*/,
double mean,
double standard_deviation,
double ratio,
double tilt,
double rot_min,
double rot_max,
{
bool did = false;
// convert 3D boxes to ordinary groups before spraying their shapes
}
/*if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) {
GSList *items = g_slist_prepend (NULL, item);
GSList *selected = NULL;
GSList *to_select = NULL;
SPDocument *doc = SP_OBJECT_DOCUMENT(item);
sp_item_list_to_curves (items, &selected, &to_select);
g_slist_free (items);
SPObject* newObj = doc->getObjectByRepr((Inkscape::XML::Node *) to_select->data);
g_slist_free (to_select);
item = (SPItem *) newObj;
// selection->add(item);
}
*/
/*if (SP_IS_GROUP(item) && !SP_IS_BOX3D(item)) {
for (SPObject *child = sp_object_first_child(SP_OBJECT(item)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
if (SP_IS_ITEM(child)) {
if (sp_spray_dilate_recursive (desktop,selection, SP_ITEM(child), p, vector, mode, radius, force, population, scale, scale_min, scale_max, reverse, mean, standard_deviation,ratio,tilt, rot_min, rot_max,_distrib))
did = true;
}
}
} else {*/
if (mode == SPRAY_MODE_COPY) {
if (a) {
if(_fid<=population)
{
// duplicate
Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio),-sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());//Move the cursor p
did = true;
}
}
} else if (mode == SPRAY_MODE_SINGLE_PATH) {
int i=1;
if (i==1) {
}
if (i==2) {
}
i++;
}
//SPObject *old_obj = doc->getObjectByRepr(old_repr);
if (a) {
if (i==2) {
}
// duplicates the father
Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio),-sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());//Move around the cursor
//unionResult and duplication
did = true;
}
}
} else if (mode == SPRAY_MODE_CLONE) {
if (a) {
if(_fid<=population)
{
//Creation of the clone
clone->setAttribute("xlink:href", g_strdup_printf("#%s", old_repr->attribute("id")), false); // Generates the link between father and son attributes
Geom::Point move = (Geom::Point(cos(tilt)*cos(dp)*dr/(1-ratio)+sin(tilt)*sin(dp)*dr/(1+ratio),-sin(tilt)*cos(dp)*dr/(1-ratio)+cos(tilt)*sin(dp)*dr/(1+ratio)))+(p-a->midpoint());
did = true;
} }}
return did;
}
SPItem */*item*/,
SPItem */*item_at_point*/,
guint32 /*fill_goal*/,
bool /*do_fill*/,
guint32 /*stroke_goal*/,
bool /*do_stroke*/,
float /*opacity_goal*/,
bool /*do_opacity*/,
bool /*do_blur*/,
bool /*reverse*/,
double /*radius*/,
double /*force*/,
bool /*do_h*/,
bool /*do_s*/,
bool /*do_l*/,
bool /*do_o*/)
{
bool did = false;
return did;
}
bool sp_spray_dilate(SPSprayContext *tc, Geom::Point /*event_p*/, Geom::Point p, Geom::Point vector, bool reverse)
{
return false;
}
bool did = false;
if (reverse) {
// RGB inversion
}
if (radius == 0 || path_force == 0) {
return false;
}
return false;
}
if (radius == 0 || path_standard_deviation == 0) {
return false;
}
if (sp_spray_dilate_recursive (desktop,selection, item, p, vector, tc->mode, radius, move_force, tc->population,tc->scale, tc->scale_min, tc->scale_max, reverse, move_mean, move_standard_deviation,tc->ratio,tc->tilt, tc->rot_min, tc->rot_max, tc->distrib))
did = true;
} else {
if (sp_spray_dilate_recursive (desktop,selection, item, p, vector, tc->mode, radius, path_force, tc->population,tc->scale, tc->scale_min, tc->scale_max, reverse, path_mean, path_standard_deviation,tc->ratio,tc->tilt, tc->rot_min, tc->rot_max, tc->distrib))
did = true;
}
}
return did;
}
{
sp_canvas_item_affine_absolute(tc->dilate_area, (sm* Geom::Rotate(tc->tilt))* Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point()));
}
{
SP_EVENT_CONTEXT(tc)->desktop->setToolboxSelectOneValue ("spray_tool_mode", mode); //sélectionne le bouton numéro "mode"
// need to set explicitly, because the prefs may not have changed by the previous
}
{
// Juggling about so that prefs have the old value but tc->mode and the button show new mode:
// button has changed prefs, restore
// changing prefs changed tc->mode, restore back :)
}
{
case GDK_ENTER_NOTIFY:
break;
case GDK_LEAVE_NOTIFY:
break;
case GDK_BUTTON_PRESS:
return TRUE;
}
tc->is_drawing = true;
tc->is_dilating = true;
tc->has_dilated = false;
tc->has_dilated=true;
}
break;
case GDK_MOTION_NOTIFY:
{
// draw the dilating cursor
sp_canvas_item_affine_absolute(tc->dilate_area, (sm*Geom::Rotate(tc->tilt))*Geom::Translate(desktop->w2d(motion_w)));
}
if (num == 0) {
tc->_message_context->flash(Inkscape::ERROR_MESSAGE, _("<b>Nothing selected!</b> Select objects to spray."));
}
// dilating:
sp_spray_dilate (tc, motion_w, motion_doc, motion_doc - tc->last_push, event->button.state & GDK_SHIFT_MASK? true : false);
//tc->last_push = motion_doc;
tc->has_dilated = true;
// it's slow, so prevent clogging up with events
return TRUE;
}
}
break;
/*Spray with the scroll*/
case GDK_SCROLL:
{
{
double temp ;
{
case GDK_SCROLL_UP:
{
{
return TRUE;
}
tc->is_drawing = true;
tc->is_dilating = true;
tc->has_dilated = false;
tc->has_dilated=true;
}
break;
case GDK_SCROLL_DOWN:
{
{
return TRUE;
}
tc->is_drawing = true;
tc->is_dilating = true;
tc->has_dilated = false;
tc->has_dilated=true;
}
break;
case GDK_SCROLL_RIGHT:
{} break;
case GDK_SCROLL_LEFT:
{} break;
}
}
break;
}
case GDK_BUTTON_RELEASE:
{
tc->is_drawing = false;
if (!tc->has_dilated) {
// if we did not rub, do a light tap
}
tc->is_dilating = false;
tc->has_dilated = false;
case SPRAY_MODE_COPY:
SP_VERB_CONTEXT_SPRAY, _("Spray with copies"));
break;
case SPRAY_MODE_CLONE:
SP_VERB_CONTEXT_SPRAY, _("Spray with clones"));
break;
case SPRAY_MODE_SINGLE_PATH:
SP_VERB_CONTEXT_SPRAY, _("Spray in single path"));
break;
}
}
break;
}
case GDK_KEY_PRESS:
case GDK_j: if (MOD__SHIFT_ONLY) {
}
case GDK_J: if (MOD__SHIFT_ONLY) {
}
break;
case GDK_m:
case GDK_M:
case GDK_0:
break;
case GDK_i:
case GDK_I:
case GDK_k: if (MOD__SHIFT_ONLY) {
}
case GDK_K:if (MOD__SHIFT_ONLY) {
}
break;
case GDK_l: if (MOD__SHIFT_ONLY) {
}
case GDK_L:
if (MOD__SHIFT_ONLY) {
}
break;
case GDK_Up:
case GDK_KP_Up:
if (!MOD__CTRL_ONLY) {
//desktop->setToolboxAdjustmentValue ("spray-force", tc->force * 100);
}
break;
case GDK_Down:
case GDK_KP_Down:
if (!MOD__CTRL_ONLY) {
//desktop->setToolboxAdjustmentValue ("spray-force", tc->force * 100);
}
break;
case GDK_Right:
case GDK_KP_Right:
if (!MOD__CTRL_ONLY) {
desktop->setToolboxAdjustmentValue ("altx-spray", tc->width * 100); // the same spinbutton is for alt+x
}
break;
case GDK_Left:
case GDK_KP_Left:
if (!MOD__CTRL_ONLY) {
}
break;
case GDK_Home:
case GDK_KP_Home:
break;
case GDK_End:
case GDK_KP_End:
break;
case GDK_x:
case GDK_X:
if (MOD__ALT_ONLY) {
}
break;
case GDK_Shift_L:
case GDK_Shift_R:
sp_spray_update_cursor(tc, true);
break;
/*Set the scale to 1*/
case GDK_Control_L:
default:
break;
}
break;
case GDK_KEY_RELEASE: {
case GDK_Shift_L:
case GDK_Shift_R:
sp_spray_update_cursor(tc, false);
break;
case GDK_Control_L:
case GDK_Control_R:
break;
default:
break;
}
}
default:
break;
}
if (!ret) {
}
}
return ret;
}
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :