~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to src/persp3d.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Ted Gould, Kees Cook
  • Date: 2009-06-24 14:00:43 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20090624140043-07stp20mry48hqup
Tags: 0.47~pre0-0ubuntu1
* New upstream release

[ Ted Gould ]
* debian/control: Adding libgsl0 and removing version specifics on boost

[ Kees Cook ]
* debian/watch: updated to run uupdate and mangle pre-release versions.
* Dropped patches that have been taken upstream:
  - 01_mips
  - 02-poppler-0.8.3
  - 03-chinese-inkscape
  - 05_fix_latex_patch
  - 06_gcc-4.4
  - 07_cdr2svg
  - 08_skip-bad-utf-on-pdf-import
  - 09_gtk-clist
  - 10_belarussian
  - 11_libpng
  - 12_desktop
  - 13_slider
  - 100_svg_import_improvements
  - 102_sp_pattern_painter_free
  - 103_bitmap_type_print

Show diffs side-by-side

added added

removed removed

Lines of Context:
30
30
static void persp3d_release(SPObject *object);
31
31
static void persp3d_set(SPObject *object, unsigned key, gchar const *value);
32
32
static void persp3d_update(SPObject *object, SPCtx *ctx, guint flags);
33
 
static Inkscape::XML::Node *persp3d_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
 
33
static Inkscape::XML::Node *persp3d_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags);
34
34
 
35
35
static void persp3d_on_repr_attr_changed (Inkscape::XML::Node * repr, const gchar *key, const gchar *oldval, const gchar *newval, bool is_interactive, void * data);
36
36
 
93
93
{
94
94
    persp->tmat = Proj::TransfMat3x4 ();
95
95
 
96
 
    persp->boxes_transformed.clear();
 
96
    persp->boxes_transformed = new std::map<SPBox3D *, bool>;
 
97
    persp->boxes_transformed->clear();
97
98
    persp->document = NULL;
98
99
 
99
100
    persp->my_counter = global_counter++;
123
124
 * Virtual release of Persp3D members before destruction.
124
125
 */
125
126
static void persp3d_release(SPObject *object) {
 
127
    Persp3D *persp = SP_PERSP3D (object);
 
128
    delete persp->boxes_transformed;
126
129
    SP_OBJECT_REPR(object)->removeListenerByData(object);
127
130
}
128
131
 
187
190
static void
188
191
persp3d_update(SPObject *object, SPCtx *ctx, guint flags)
189
192
{
190
 
    if (flags & SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG) {
 
193
    if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
191
194
 
192
195
        /* TODO: Should we update anything here? */
193
196
 
227
230
        str = proj_origin.coord_string();
228
231
        repr->setAttribute("inkscape:persp3d-origin", str);
229
232
        g_free (str);
230
 
        Inkscape::GC::release(repr);
231
233
    }
232
234
 
233
235
    /* Append the new persp3d to defs */
254
256
 * Virtual write: write object attributes to repr.
255
257
 */
256
258
static Inkscape::XML::Node *
257
 
persp3d_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
 
259
persp3d_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
258
260
{
259
261
    Persp3D *persp = SP_PERSP3D(object);
260
262
 
261
263
    if ((flags & SP_OBJECT_WRITE_BUILD & SP_OBJECT_WRITE_EXT) && !repr) {
262
264
        // this is where we end up when saving as plain SVG (also in other circumstances?);
263
265
        // hence we don't set the sodipodi:type attribute
264
 
        Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
265
266
        repr = xml_doc->createElement("inkscape:perspective");
266
267
    }
267
268
 
281
282
    }
282
283
 
283
284
    if (((SPObjectClass *) persp3d_parent_class)->write)
284
 
        (* ((SPObjectClass *) persp3d_parent_class)->write)(object, repr, flags);
 
285
        (* ((SPObjectClass *) persp3d_parent_class)->write)(object, xml_doc, repr, flags);
285
286
 
286
287
    return repr;
287
288
}
288
289
 
289
290
/* convenience wrapper around persp3d_get_finite_dir() and persp3d_get_infinite_dir() */
290
 
NR::Point persp3d_get_PL_dir_from_pt (Persp3D *persp, NR::Point const &pt, Proj::Axis axis) {
 
291
Geom::Point persp3d_get_PL_dir_from_pt (Persp3D *persp, Geom::Point const &pt, Proj::Axis axis) {
291
292
    if (persp3d_VP_is_finite(persp, axis)) {
292
293
        return persp3d_get_finite_dir(persp, pt, axis);
293
294
    } else {
295
296
    }
296
297
}
297
298
 
298
 
NR::Point
299
 
persp3d_get_finite_dir (Persp3D *persp, NR::Point const &pt, Proj::Axis axis) {
 
299
Geom::Point
 
300
persp3d_get_finite_dir (Persp3D *persp, Geom::Point const &pt, Proj::Axis axis) {
300
301
    Box3D::PerspectiveLine pl(pt, axis, persp);
301
302
    return pl.direction();
302
303
}
303
304
 
304
 
NR::Point
 
305
Geom::Point
305
306
persp3d_get_infinite_dir (Persp3D *persp, Proj::Axis axis) {
306
307
    Proj::Pt2 vp(persp3d_get_VP(persp, axis));
307
308
    if (vp[2] != 0.0) {
308
309
        g_print ("VP should be infinite but is (%f : %f : %f)\n", vp[0], vp[1], vp[2]);
309
 
        g_return_val_if_fail(vp[2] != 0.0, NR::Point(0.0, 0.0));
 
310
        g_return_val_if_fail(vp[2] != 0.0, Geom::Point(0.0, 0.0));
310
311
    }
311
 
    return NR::Point(vp[0], vp[1]);
 
312
    return Geom::Point(vp[0], vp[1]);
312
313
}
313
314
 
314
315
double
337
338
 
338
339
/* toggle VPs for the same axis in all perspectives of a given list */
339
340
void
340
 
persp3d_toggle_VPs (std::set<Persp3D *> p, Proj::Axis axis) {
341
 
    for (std::set<Persp3D *>::iterator i = p.begin(); i != p.end(); ++i) {
 
341
persp3d_toggle_VPs (std::list<Persp3D *> p, Proj::Axis axis) {
 
342
    for (std::list<Persp3D *>::iterator i = p.begin(); i != p.end(); ++i) {
342
343
        persp3d_toggle_VP((*i), axis, false);
343
344
    }
344
345
    sp_document_done(sp_desktop_document(inkscape_active_desktop()), SP_VERB_CONTEXT_3DBOX,
360
361
        return;
361
362
    }
362
363
    Proj::Pt2 v_dir_proj (persp->tmat.column(axis));
363
 
    NR::Point v_dir (v_dir_proj[0], v_dir_proj[1]);
364
 
    double a = NR::atan2 (v_dir) * 180/M_PI;
 
364
    Geom::Point v_dir (v_dir_proj[0], v_dir_proj[1]);
 
365
    double a = Geom::atan2 (v_dir) * 180/M_PI;
365
366
    a += alt_pressed ? 0.5 * ((angle > 0 ) - (angle < 0)) : angle; // the r.h.s. yields +/-0.5 or angle
366
367
    persp->tmat.set_infinite_direction (axis, a);
367
368
 
375
376
}
376
377
 
377
378
void
378
 
persp3d_apply_affine_transformation (Persp3D *persp, NR::Matrix const &xform) {
 
379
persp3d_apply_affine_transformation (Persp3D *persp, Geom::Matrix const &xform) {
379
380
    persp->tmat *= xform;
380
381
    persp3d_update_box_reprs(persp);
381
382
    SP_OBJECT(persp)->updateRepr(SP_OBJECT_WRITE_EXT);
420
421
 
421
422
void
422
423
persp3d_add_box_transform (Persp3D *persp, SPBox3D *box) {
423
 
    std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed.find(box);
424
 
    if (i != persp->boxes_transformed.end() && (*i).second == true) {
 
424
    std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed->find(box);
 
425
    if (i != persp->boxes_transformed->end() && (*i).second == true) {
425
426
        g_print ("Warning! In %s (%d): trying to add transform status for box %d twice when it's already listed as true.\n", SP_OBJECT_REPR(persp)->attribute("id"), persp->my_counter, box->my_counter);
426
427
        return;
427
428
    }
428
429
 
429
 
    persp->boxes_transformed[box] = false;
 
430
    (*persp->boxes_transformed)[box] = false;
430
431
}
431
432
 
432
433
void
433
434
persp3d_remove_box_transform (Persp3D *persp, SPBox3D *box) {
434
 
    persp->boxes_transformed.erase(box);
 
435
    persp->boxes_transformed->erase(box);
435
436
}
436
437
 
437
438
void
438
439
persp3d_set_box_transformed (Persp3D *persp, SPBox3D *box, bool transformed) {
439
 
    if (persp->boxes_transformed.find(box) == persp->boxes_transformed.end()) {
 
440
    if (persp->boxes_transformed->find(box) == persp->boxes_transformed->end()) {
440
441
        g_print ("Warning! In %s (%d): trying to set transform status for box %d, but it is not listed in the perspective!! Aborting.\n",
441
442
                 SP_OBJECT_REPR(persp)->attribute("id"), persp->my_counter,
442
443
                 box->my_counter);
443
444
        return;
444
445
    }
445
446
 
446
 
    persp->boxes_transformed[box] = transformed;
 
447
    (*persp->boxes_transformed)[box] = transformed;
447
448
}
448
449
 
449
450
bool
450
451
persp3d_was_transformed (Persp3D *persp) {
451
 
    if (persp->boxes_transformed.size() == 1) {
 
452
    if (persp->boxes_transformed->size() == 1) {
452
453
        /* either the transform has not been applied to the single box associated to this perspective yet
453
454
           or the transform was already reset; in both cases we need to return false because upcoming
454
455
           transforms need to be applied */
455
 
        (*persp->boxes_transformed.begin()).second = false; // make sure the box is marked as untransformed (in case more boxes are added later)
 
456
        (*persp->boxes_transformed->begin()).second = false; // make sure the box is marked as untransformed (in case more boxes are added later)
456
457
        return false;
457
458
    }
458
459
 
459
 
    for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed.begin();
460
 
         i != persp->boxes_transformed.end(); ++i) {
 
460
    for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed->begin();
 
461
         i != persp->boxes_transformed->end(); ++i) {
461
462
        if ((*i).second == true) {
462
463
            // at least one of the boxes in the perspective has already been transformed;
463
464
            return true;
468
469
 
469
470
bool
470
471
persp3d_all_transformed(Persp3D *persp) {
471
 
    for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed.begin();
472
 
         i != persp->boxes_transformed.end(); ++i) {
 
472
    for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed->begin();
 
473
         i != persp->boxes_transformed->end(); ++i) {
473
474
        if ((*i).second == false) {
474
475
            return false;
475
476
        }
479
480
 
480
481
void
481
482
persp3d_unset_transforms(Persp3D *persp) {
482
 
    for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed.begin();
483
 
         i != persp->boxes_transformed.end(); ++i) {
 
483
    for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed->begin();
 
484
         i != persp->boxes_transformed->end(); ++i) {
484
485
        (*i).second = false;
485
486
    }
486
487
}
563
564
    persp3d_update_box_displays (persp);
564
565
}
565
566
 
566
 
/* returns a std::set() of all perspectives of the currently selected boxes */
567
 
std::set<Persp3D *>
568
 
persp3d_currently_selected_persps (SPEventContext *ec) {
569
 
    Inkscape::Selection *selection = sp_desktop_selection (ec->desktop);
570
 
 
571
 
    std::set<Persp3D *> p;
572
 
    for (GSList *i = (GSList *) selection->itemList(); i != NULL; i = i->next) {
573
 
        if (SP_IS_BOX3D (i->data)) {
574
 
            p.insert(box3d_get_perspective(SP_BOX3D(i->data)));
575
 
        }
576
 
    }
577
 
    return p;
578
 
}
579
 
 
580
567
/* checks whether all boxes linked to this perspective are currently selected */
581
568
bool
582
569
persp3d_has_all_boxes_in_selection (Persp3D *persp) {
583
 
    const GSList *selection = sp_desktop_selection (inkscape_active_desktop())->itemList();
 
570
    std::list<SPBox3D *> selboxes = sp_desktop_selection(inkscape_active_desktop())->box3DList();
584
571
 
585
572
    for (std::vector<SPBox3D *>::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) {
586
 
        if (g_slist_find((GSList *) selection, *i) == NULL) {
 
573
        if (std::find(selboxes.begin(), selboxes.end(), *i) == selboxes.end()) {
587
574
            // we have an unselected box in the perspective
588
575
            return false;
589
576
        }
591
578
    return true;
592
579
}
593
580
 
594
 
std::list<SPBox3D *>
595
 
persp3d_selected_boxes (Persp3D *persp) {
596
 
    const GSList *selection = sp_desktop_selection (inkscape_active_desktop())->itemList();
597
 
    std::list<SPBox3D *> sel;
598
 
 
599
 
    for (std::vector<SPBox3D *>::iterator i = persp->boxes.begin(); i != persp->boxes.end(); ++i) {
600
 
        if (g_slist_find((GSList *) selection, *i) != NULL) {
601
 
            sel.push_back(SP_BOX3D(*i));
602
 
        }
603
 
    }
604
 
    return sel;
 
581
/**
 
582
 * For each perspective having a box in \a selection, determine all its unselected boxes.
 
583
 */
 
584
// TODO: Check where we can use pass-by-reference (or so) instead of recreating all the lists afresh.
 
585
std::map<Persp3D *, std::list<SPBox3D *> >
 
586
persp3d_unselected_boxes(Inkscape::Selection *selection) {
 
587
    std::list<Persp3D *> plist = selection->perspList();
 
588
    std::map<Persp3D *, std::list<SPBox3D *> > punsel;
 
589
 
 
590
    std::list<Persp3D *>::iterator i;
 
591
    std::vector<SPBox3D *>::iterator j;
 
592
    // for all perspectives in the list ...
 
593
    for (i = plist.begin(); i != plist.end(); ++i) {
 
594
        Persp3D *persp = *i;
 
595
        // ... and each box associated to it ...
 
596
        for (j = persp->boxes.begin(); j != persp->boxes.end(); ++j) {
 
597
            SPBox3D *box = *j;
 
598
            // ... check whether it is unselected, and if so add it to the list
 
599
            if (persp->boxes_transformed->find(box) == persp->boxes_transformed->end()) {
 
600
                punsel[persp].push_back(box);
 
601
            }
 
602
        }
 
603
    }
 
604
    return punsel;
 
605
}
 
606
 
 
607
/**
 
608
 * Split all perspectives with a box in \a selection by moving their unselected boxes to newly
 
609
 * created perspectives.
 
610
 */
 
611
void
 
612
persp3d_split_perspectives_according_to_selection(Inkscape::Selection *selection) {
 
613
    std::map<Persp3D *, std::list<SPBox3D *> > punsel = persp3d_unselected_boxes(selection);
 
614
 
 
615
    std::map<Persp3D *, std::list<SPBox3D *> >::iterator i;
 
616
    std::list<SPBox3D *>::iterator j;
 
617
    // for all perspectives in the list ...
 
618
    for (i = punsel.begin(); i != punsel.end(); ++i) {
 
619
        Persp3D *persp = (*i).first;
 
620
        // ... if the perspective has unselected boxes ...
 
621
        if (!(*i).second.empty()) {
 
622
            // create a new perspective and move these boxes over
 
623
            Persp3D * new_persp = persp3d_create_xml_element (SP_OBJECT_DOCUMENT(persp), persp);
 
624
            for (j = (*i).second.begin(); j != (*i).second.end(); ++j) {
 
625
                SPBox3D *box = *j;
 
626
                box3d_switch_perspectives(box, persp, new_persp);
 
627
            }
 
628
        }
 
629
    }
605
630
}
606
631
 
607
632
/* some debugging stuff follows */
645
670
    g_print ("\n======================================\n");
646
671
    g_print ("Selected perspectives and their boxes:\n");
647
672
 
648
 
    std::set<Persp3D *> sel_persps = persp3d_currently_selected_persps (inkscape_active_event_context());
 
673
    std::list<Persp3D *> sel_persps = sp_desktop_selection(inkscape_active_desktop())->perspList();
649
674
 
650
 
    for (std::set<Persp3D *>::iterator j = sel_persps.begin(); j != sel_persps.end(); ++j) {
 
675
    for (std::list<Persp3D *>::iterator j = sel_persps.begin(); j != sel_persps.end(); ++j) {
651
676
        Persp3D *persp = SP_PERSP3D(*j);
652
677
        g_print ("  %s (%d):  ", SP_OBJECT_REPR(persp)->attribute("id"), persp->my_counter);
653
 
        for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed.begin();
654
 
             i != persp->boxes_transformed.end(); ++i) {
 
678
        for (std::map<SPBox3D *, bool>::iterator i = persp->boxes_transformed->begin();
 
679
             i != persp->boxes_transformed->end(); ++i) {
655
680
            g_print ("<%d,%d> ", (*i).first->my_counter, (*i).second);
656
681
        }
657
682
        g_print ("\n");