8
6
* Lauris Kaplinski <lauris@kaplinski.com>
9
7
* bulia byak <buliabyak@users.sf.net>
10
8
* MenTaLguY <mental@rydia.net>
12
11
* The original dynadraw code:
13
12
* Paul Haeberli <paul@sgi.com>
35
34
#include "svg/svg.h"
36
35
#include "display/canvas-bpath.h"
37
#include <2geom/isnan.h>
36
#include "display/cairo-utils.h"
37
#include <2geom/math-utils.h>
38
38
#include <2geom/pathvector.h>
39
39
#include <2geom/bezier-utils.h>
40
40
#include "display/curve.h"
59
59
#include "sp-shape.h"
60
60
#include "sp-path.h"
61
61
#include "sp-text.h"
62
#include "display/sp-canvas.h"
62
63
#include "display/canvas-bpath.h"
63
64
#include "display/canvas-arena.h"
64
65
#include "livarot/Shape.h"
66
67
#include "dyna-draw-context.h"
69
using Inkscape::DocumentUndo;
68
71
#define DDC_RED_RGBA 0xff0000ff
70
73
#define TOLERANCE_CALLIGRAPHIC 0.1
437
440
double trace_thick = 1;
438
441
if (dc->trace_bg) {
439
442
// pick single pixel
441
int x = (int) floor(brush_w[Geom::X]);
442
int y = (int) floor(brush_w[Geom::Y]);
443
nr_pixblock_setup_fast(&pb, NR_PIXBLOCK_MODE_R8G8B8A8P, x, y, x+1, y+1, TRUE);
444
sp_canvas_arena_render_pixblock(SP_CANVAS_ARENA(sp_desktop_drawing(SP_EVENT_CONTEXT(dc)->desktop)), &pb);
445
const unsigned char *s = NR_PIXBLOCK_PX(&pb);
446
double R = s[0] / 255.0;
447
double G = s[1] / 255.0;
448
double B = s[2] / 255.0;
449
double A = s[3] / 255.0;
444
Geom::IntRect area = Geom::IntRect::from_xywh(brush_w.floor(), Geom::IntPoint(1, 1));
445
cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
446
sp_canvas_arena_render_surface(SP_CANVAS_ARENA(sp_desktop_drawing(SP_EVENT_CONTEXT(dc)->desktop)), s, area);
447
ink_cairo_surface_average_color_premul(s, R, G, B, A);
448
cairo_surface_destroy(s);
450
449
double max = MAX (MAX (R, G), B);
451
450
double min = MIN (MIN (R, G), B);
452
451
double L = A * (max + min)/2 + (1 - A); // blend with white bg
581
580
Geom::Point hatch_unit_vector(0,0);
582
581
Geom::Point nearest(0,0);
583
582
Geom::Point pointer(0,0);
584
Geom::Matrix motion_to_curve(Geom::identity());
583
Geom::Affine motion_to_curve(Geom::identity());
586
585
if (event->motion.state & GDK_CONTROL_MASK) { // hatching - sense the item
601
600
// calculate pointer point in the guide item's coords
602
motion_to_curve = sp_item_dt2i_affine(selected) * sp_item_i2doc_affine(selected);
601
motion_to_curve = selected->dt2i_affine() * selected->i2doc_affine();
603
602
pointer = motion_dt * motion_to_curve;
605
604
// calculate the nearest point on the guide path
778
777
if (dc->hatch_spacing == 0 && hatch_dist != 0) {
779
778
// Haven't set spacing yet: gray, center free, update radius live
780
779
Geom::Point c = desktop->w2d(motion_w);
781
Geom::Matrix const sm (Geom::Scale(hatch_dist, hatch_dist) * Geom::Translate(c));
780
Geom::Affine const sm (Geom::Scale(hatch_dist, hatch_dist) * Geom::Translate(c));
782
781
sp_canvas_item_affine_absolute(dc->hatch_area, sm);
783
782
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0x7f7f7fff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
784
783
sp_canvas_item_show(dc->hatch_area);
785
784
} else if (dc->dragging && !dc->hatch_escaped) {
786
785
// Tracking: green, center snapped, fixed radius
787
786
Geom::Point c = motion_dt;
788
Geom::Matrix const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
787
Geom::Affine const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
789
788
sp_canvas_item_affine_absolute(dc->hatch_area, sm);
790
789
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0x00FF00ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
791
790
sp_canvas_item_show(dc->hatch_area);
792
791
} else if (dc->dragging && dc->hatch_escaped) {
793
792
// Tracking escaped: red, center free, fixed radius
794
793
Geom::Point c = motion_dt;
795
Geom::Matrix const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
794
Geom::Affine const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
797
796
sp_canvas_item_affine_absolute(dc->hatch_area, sm);
798
797
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0xFF0000ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
801
800
// Not drawing but spacing set: gray, center snapped, fixed radius
802
801
Geom::Point c = (nearest + dc->hatch_spacing * hatch_unit_vector) * motion_to_curve.inverse();
803
802
if (!IS_NAN(c[Geom::X]) && !IS_NAN(c[Geom::Y])) {
804
Geom::Matrix const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
803
Geom::Affine const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c));
805
804
sp_canvas_item_affine_absolute(dc->hatch_area, sm);
806
805
sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0x7f7f7fff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
807
806
sp_canvas_item_show(dc->hatch_area);
1002
1001
if (!dc->accumulated->is_empty()) {
1003
1002
if (!dc->repr) {
1004
1003
/* Create object */
1005
Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc());
1004
Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
1006
1005
Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
1008
1007
/* Set style */
1013
1012
SPItem *item=SP_ITEM(desktop->currentLayer()->appendChildRepr(dc->repr));
1014
1013
Inkscape::GC::release(dc->repr);
1015
item->transform = sp_item_i2doc_affine(SP_ITEM(desktop->currentLayer())).inverse();
1014
item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse();
1016
1015
item->updateRepr();
1018
1017
Geom::PathVector pathv = dc->accumulated->get_pathvector() * desktop->dt2doc();
1040
1039
dc->repr = NULL;
1043
sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_CALLIGRAPHIC,
1044
_("Draw calligraphic stroke"));
1042
DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_CALLIGRAPHIC,
1043
_("Draw calligraphic stroke"));
1084
1083
return false; // failure
1087
Geom::CubicBezier const * dc_cal1_firstseg = dynamic_cast<Geom::CubicBezier const *>( dc->cal1->first_segment() );
1088
Geom::CubicBezier const * rev_cal2_firstseg = dynamic_cast<Geom::CubicBezier const *>( rev_cal2->first_segment() );
1089
Geom::CubicBezier const * dc_cal1_lastseg = dynamic_cast<Geom::CubicBezier const *>( dc->cal1->last_segment() );
1090
Geom::CubicBezier const * rev_cal2_lastseg = dynamic_cast<Geom::CubicBezier const *>( rev_cal2->last_segment() );
1093
!dc_cal1_firstseg ||
1094
!rev_cal2_firstseg ||
1101
return false; // failure
1086
Geom::Curve const * dc_cal1_firstseg = dc->cal1->first_segment();
1087
Geom::Curve const * rev_cal2_firstseg = rev_cal2->first_segment();
1088
Geom::Curve const * dc_cal1_lastseg = dc->cal1->last_segment();
1089
Geom::Curve const * rev_cal2_lastseg = rev_cal2->last_segment();
1104
1091
dc->accumulated->reset(); /* Is this required ?? */
1106
1093
dc->accumulated->append(dc->cal1, false);
1108
add_cap(dc->accumulated, (*dc_cal1_lastseg)[3], (*rev_cal2_firstseg)[0], dc->cap_rounding);
1095
add_cap(dc->accumulated, dc_cal1_lastseg->finalPoint(), rev_cal2_firstseg->initialPoint(), dc->cap_rounding);
1110
1097
dc->accumulated->append(rev_cal2, true);
1112
add_cap(dc->accumulated, (*rev_cal2_lastseg)[3], (*dc_cal1_firstseg)[0], dc->cap_rounding);
1099
add_cap(dc->accumulated, rev_cal2_lastseg->finalPoint(), dc_cal1_firstseg->initialPoint(), dc->cap_rounding);
1114
1101
dc->accumulated->closepath();