draw-context.cpp revision 70278f4200aa074f6f1cf01ef3c5cceb5aefa6e5
#define __SP_DRAW_CONTEXT_C__
/*
* Generic drawing context
*
* Author:
* Lauris Kaplinski <lauris@kaplinski.com>
*
* Copyright (C) 2000 Lauris Kaplinski
* Copyright (C) 2000-2001 Ximian, Inc.
* Copyright (C) 2002 Lauris Kaplinski
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#define DRAW_VERBOSE
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <gdk/gdkkeysyms.h>
#include "display/canvas-bpath.h"
#include "libnr/n-art-bpath.h"
#include "desktop.h"
#include "desktop-affine.h"
#include "desktop-handles.h"
#include "desktop-style.h"
#include "document.h"
#include "draw-anchor.h"
#include "macros.h"
#include "message-stack.h"
#include "pen-context.h"
#include "prefs-utils.h"
#include "selection.h"
#include "selection-chemistry.h"
#include "snap.h"
#include "sp-path.h"
#include "sp-namedview.h"
#include "live_effects/lpe-patternalongpath.h"
#include "style.h"
static SPEventContextClass *draw_parent_class;
sp_draw_context_get_type(void)
{
if (!type) {
sizeof(SPDrawContextClass),
sizeof(SPDrawContext),
4,
NULL, /* value_table */
};
}
return type;
}
static void
{
}
static void
{
dc->red_curve_is_valid = false;
}
static void
{
}
}
}
static void
{
}
/* Connect signals to track selection changes */
);
);
/* Create red bpath */
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->red_bpath), dc->red_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
/* Create red curve */
/* Create blue bpath */
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->blue_bpath), dc->blue_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
/* Create blue curve */
/* Create green curve */
/* No green anchor by default */
}
static void
{
}
}
}
static void
{
}
{
case GDK_KEY_PRESS:
case GDK_Up:
case GDK_Down:
case GDK_KP_Up:
case GDK_KP_Down:
// prevent the zoom field from activation
if (!MOD__CTRL_ONLY) {
}
break;
default:
break;
}
break;
default:
break;
}
if (!ret) {
}
}
return ret;
}
static char const *
{
return ( SP_IS_PEN_CONTEXT(dc)
? "tools.freehand.pen"
: "tools.freehand.pencil" );
}
static void
{
using namespace Inkscape::LivePathEffect;
// TODO: Don't paste path if nothing is on the clipboard
}
/*
* If we have an item and a waiting LPE, apply the effect to the item
* (spiro spline mode is treated separately)
*/
void
{
using namespace Inkscape::LivePathEffect;
}
bool shape_applied = false;
#define SHAPE_LENGTH 100
#define SHAPE_HEIGHT 10
switch (shape) {
case 0:
// don't apply any shape
break;
case 1:
{
// "triangle in"
// TODO: this is only for illustration (we create a "decrescendo"-shaped path
// manually; eventually we should read the path from a separate file)
c->moveto(0,0);
c->lineto(0, SHAPE_HEIGHT);
c->closepath();
c->unref();
shape_applied = true;
break;
}
case 2:
{
// "triangle out"
c->lineto(SHAPE_LENGTH, 0);
c->closepath();
c->unref();
shape_applied = true;
break;
}
case 3:
{
// "ellipse"
const double C1 = 0.552;
c->curveto((1 + C1) * SHAPE_LENGTH/2, 0, SHAPE_LENGTH, (1 - C1) * SHAPE_HEIGHT/2, SHAPE_LENGTH, SHAPE_HEIGHT/2);
c->curveto(SHAPE_LENGTH, (1 + C1) * SHAPE_HEIGHT/2, (1 + C1) * SHAPE_LENGTH/2, SHAPE_HEIGHT, SHAPE_LENGTH/2, SHAPE_HEIGHT);
c->curveto((1 - C1) * SHAPE_LENGTH/2, SHAPE_HEIGHT, 0, (1 + C1) * SHAPE_HEIGHT/2, 0, SHAPE_HEIGHT/2);
c->closepath();
c->unref();
shape_applied = true;
break;
}
case 4:
{
// take shape from clipboard; TODO: catch the case where clipboard is empty
shape_applied = true;
break;
}
default:
break;
}
if (shape_applied) {
// apply original stroke color as fill and unset stroke; then return
return;
}
}
if (SP_IS_PEN_CONTEXT(dc)) {
SP_PEN_CONTEXT(dc)->polylines_only = (prefs_get_int_attribute("tools.freehand.pen", "freehand-mode", 0) == 2);
}
}
}
/*
* Selection handlers
*/
static void
{
}
}
/* fixme: We have to ensure this is not delayed (Lauris) */
static void
{
}
}
static void
{
/* Create new white data */
/* Item */
/* Curve list */
/* We keep it in desktop coordinates to eliminate calculation errors */
/* Anchor list */
SPCurve *c;
g_return_if_fail( c->get_segment_count() > 0 );
if ( !c->is_closed() ) {
SPDrawAnchor *a;
}
}
/* fixme: recalculate active anchor? */
}
}
/**
* Snaps node or handle to PI/rotationsnapsperpi degree increments.
*
* \param dc draw context
* \param p cursor point (to be changed by snapping)
* \param o origin point
* \param state keyboard state to check if ctrl was pressed
*/
{
/* Control must be down for this snap to work */
if ((state & GDK_CONTROL_MASK) == 0) {
return;
}
/* 0 means no snapping. */
/* mirrored by fabs, so this corresponds to 15 degrees */
double bdot = 0;
for (unsigned i = 0; i < snaps; i++) {
/* I think it is better numerically to use the normal, rather than the dot product
* to assess solutions, but I haven't proven it. */
best = v;
}
v = t;
}
/* Snap it along best vector */
m.constrainedSnapReturnByRef( Inkscape::Snapper::SNAPPOINT_NODE, p, Inkscape::Snapper::ConstraintLine(best));
}
}
{
/* Shift disables this snap */
if (state & GDK_SHIFT_MASK) {
return;
}
}
static SPCurve *
{
return ret;
}
/**
* Concats red, blue and green.
* If any anchors are defined, process these, optionally removing curves from white list
* Invoke _flush_white to write result back to object.
*/
void
{
/* Concat RBG */
/* Green */
while (dc->green_bpaths) {
}
/* Blue */
/* Red */
if (dc->red_curve_is_valid) {
}
if (c->is_empty()) {
c->unref();
return;
}
/* Step A - test, whether we ended on green anchor */
// We hit green anchor, closing Green-Blue-Red
SP_EVENT_CONTEXT_DESKTOP(dc)->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Path is closed."));
c->closepath_current();
/* Closed path, just flush */
spdc_flush_white(dc, c);
c->unref();
return;
}
/* Step B - both start and end anchored to same curve */
{
// We hit bot start and end of single curve, closing paths
c = reverse_then_unref(c);
}
c->unref();
return;
}
/* Step C - test start */
s = reverse_then_unref(s);
}
s->append_continuous(c, 0.0625);
c->unref();
c = s;
e = reverse_then_unref(e);
}
c->append_continuous(e, 0.0625);
e->unref();
}
spdc_flush_white(dc, c);
c->unref();
}
/*
* Flushes white curve(s) and additional curve into object
*
* No cleaning of colored curves - this has to be done by caller
* No rereading of white data, so if you cannot rely on ::modified, do it in caller
*
*/
static void
{
SPCurve *c;
if (dc->white_curves) {
if (gc) {
}
} else if (gc) {
c = gc;
c->ref();
} else {
return;
}
/* Now we have to go back to item coordinates at last */
if ( c && !c->is_empty() ) {
/* We actually have something to write */
bool has_lpe = false;
if (dc->white_item) {
} else {
/* Set style */
}
if (has_lpe)
else
if (!dc->white_item) {
/* Attach repr */
item->updateRepr();
}
// we finished the path; now apply any waiting LPEs or freehand shapes
// FIXME: placing this here seems to cause issues with undo!
_("Draw path"));
// When quickly drawing several subpaths with Shift, the next subpath may be finished and
// flushed before the selection_modified signal is fired by the previous change, which
// results in the tool losing all of the selected path's curve except that last subpath. To
// fix this, we force the selection_modified callback now, to make sure the tool's curve is
// in sync immediately.
}
c->unref();
/* Flush pending updates */
}
/**
* Returns FIRST active anchor (the activated one).
*/
{
/* Test green anchor */
if (dc->green_anchor) {
}
}
}
return active;
}
static void
{
if (dc->white_item) {
/* We do not hold refcount */
}
while (dc->white_curves) {
}
while (dc->white_anchors) {
}
}
static void
{
/* Red */
}
}
/* Blue */
if (dc->blue_bpath) {
}
if (dc->blue_curve) {
}
/* Green */
while (dc->green_bpaths) {
}
if (dc->green_curve) {
}
if (dc->green_anchor) {
}
/* White */
if (dc->white_item) {
/* We do not hold refcount */
}
while (dc->white_curves) {
}
while (dc->white_anchors) {
}
}
/*
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 :