~ubuntu-branches/debian/experimental/inkscape/experimental

« back to all changes in this revision

Viewing changes to src/sp-ellipse.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Thomas Viehmann
  • Date: 2008-09-09 23:29:02 UTC
  • mfrom: (1.1.7 upstream)
  • Revision ID: james.westby@ubuntu.com-20080909232902-c50iujhk1w79u8e7
Tags: 0.46-2.1
* Non-maintainer upload.
* Add upstream patch fixing a crash in the open dialog
  in the zh_CN.utf8 locale. Closes: #487623.
  Thanks to Luca Bruno for the patch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
#include "libnr/nr-path.h"
24
24
#include "libnr/nr-matrix-fns.h"
25
25
#include "svg/svg.h"
26
 
#include "svg/stringstream.h"
 
26
#include "svg/path-string.h"
27
27
#include "xml/repr.h"
28
28
#include "attributes.h"
29
29
#include "style.h"
30
30
#include "display/curve.h"
31
31
#include <glibmm/i18n.h>
32
32
 
 
33
#include "document.h"
33
34
#include "sp-ellipse.h"
34
35
 
35
36
#include "prefs-utils.h"
75
76
static void sp_genericellipse_snappoints(SPItem const *item, SnapPointsIter p);
76
77
 
77
78
static void sp_genericellipse_set_shape(SPShape *shape);
 
79
static void sp_genericellipse_update_patheffect (SPShape *shape, bool write);
 
80
 
78
81
static Inkscape::XML::Node *sp_genericellipse_write(SPObject *object, Inkscape::XML::Node *repr,
79
82
                                                    guint flags);
80
83
 
118
121
    item_class->snappoints = sp_genericellipse_snappoints;
119
122
 
120
123
    shape_class->set_shape = sp_genericellipse_set_shape;
 
124
    shape_class->update_patheffect = sp_genericellipse_update_patheffect;
121
125
}
122
126
 
123
127
static void
153
157
        ((SPObjectClass *) ge_parent_class)->update(object, ctx, flags);
154
158
}
155
159
 
 
160
static void
 
161
sp_genericellipse_update_patheffect(SPShape *shape, bool write)
 
162
{
 
163
    sp_genericellipse_set_shape(shape);
 
164
 
 
165
    if (write) {
 
166
        Inkscape::XML::Node *repr = SP_OBJECT_REPR(shape);
 
167
        if ( shape->curve != NULL ) {
 
168
            NArtBpath *abp = sp_curve_first_bpath(shape->curve);
 
169
            if (abp) {
 
170
                gchar *str = sp_svg_write_path(abp);
 
171
                repr->setAttribute("d", str);
 
172
                g_free(str);
 
173
            } else {
 
174
                repr->setAttribute("d", "");
 
175
            }
 
176
        } else {
 
177
            repr->setAttribute("d", NULL);
 
178
        }
 
179
    }
 
180
 
 
181
    ((SPObject *)shape)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
 
182
}
 
183
 
 
184
 
156
185
#define C1 0.552
157
186
 
158
187
/* fixme: Think (Lauris) */
159
188
 
160
189
static void sp_genericellipse_set_shape(SPShape *shape)
161
190
{
162
 
    double cx, cy, rx, ry, s, e;
 
191
    double rx, ry, s, e;
163
192
    double x0, y0, x1, y1, x2, y2, x3, y3;
164
193
    double len;
165
194
    gint slice = FALSE;
172
201
 
173
202
    sp_genericellipse_normalize(ellipse);
174
203
 
175
 
    cx = 0.0;
176
 
    cy = 0.0;
177
204
    rx = ellipse->rx.computed;
178
205
    ry = ellipse->ry.computed;
179
206
 
247
274
    SPCurve *c = sp_curve_new_from_bpath(nr_artpath_affine(bpath, aff));
248
275
    g_assert(c != NULL);
249
276
 
 
277
    sp_shape_perform_path_effect(c, SP_SHAPE (ellipse));
250
278
    sp_shape_set_curve_insync((SPShape *) ellipse, c, TRUE);
251
279
    sp_curve_unref(c);
252
280
}
253
281
 
254
282
static void sp_genericellipse_snappoints(SPItem const *item, SnapPointsIter p)
255
283
{
256
 
    SPGenericEllipse const *ge = SP_GENERICELLIPSE(item);
257
 
 
 
284
    g_assert(item != NULL);
 
285
    g_assert(SP_IS_GENERICELLIPSE(item));
 
286
    
 
287
    SPGenericEllipse *ellipse = SP_GENERICELLIPSE(item);
 
288
    sp_genericellipse_normalize(ellipse);
258
289
    NR::Matrix const i2d = sp_item_i2d_affine(item);
259
290
 
260
 
    /* Add the centre */
261
 
    *p = NR::Point(ge->cx.computed, ge->cy.computed) * i2d;
 
291
    // figure out if we have a slice, whilst guarding against rounding errors
 
292
    bool slice = false;
 
293
    double len = fmod(ellipse->end - ellipse->start, SP_2PI);
 
294
    if (len < 0.0) len += SP_2PI;
 
295
    if (fabs(len) < 1e-8 || fabs(len - SP_2PI) < 1e-8) {
 
296
        slice = false;
 
297
        ellipse->end = ellipse->start + SP_2PI;
 
298
    } else {
 
299
        slice = true;
 
300
    }
262
301
 
263
 
    // TODO: add the ends of radii
 
302
    double rx = ellipse->rx.computed;
 
303
    double ry = ellipse->ry.computed;    
 
304
    double cx = ellipse->cx.computed;
 
305
    double cy = ellipse->cy.computed;
 
306
    
 
307
    // Snap to the 4 quadrant points of the ellipse, but only if the arc
 
308
    // spans far enough to include them
 
309
    double angle = 0;
 
310
    for (angle = 0; angle < SP_2PI; angle += M_PI_2) {
 
311
        if (angle >= ellipse->start && angle <= ellipse->end) {
 
312
            *p = NR::Point(cx + cos(angle)*rx, cy + sin(angle)*ry) * i2d;
 
313
        }
 
314
    }
 
315
    
 
316
    // And if we have a slice, also snap to the endpoints and the centre point 
 
317
    if (slice) {
 
318
        // Add the centre, if we have a closed slice
 
319
        if (ellipse->closed) {
 
320
            *p = NR::Point(cx, cy) * i2d;
 
321
        }
 
322
        // Add the start point, if it's not coincident with a quadrant point
 
323
        if (fmod(ellipse->start, M_PI_2) != 0.0 ) {    
 
324
            *p = NR::Point(cx + cos(ellipse->start)*rx, cy + sin(ellipse->start)*ry) * i2d;
 
325
        } 
 
326
        // Add the end point, if it's not coincident with a quadrant point
 
327
        if (fmod(ellipse->end, M_PI_2) != 0.0 ) {    
 
328
            *p = NR::Point(cx + cos(ellipse->end)*rx, cy + sin(ellipse->end)*ry) * i2d;
 
329
        }
 
330
    }
264
331
}
265
332
 
266
333
void
284
351
 
285
352
    if (flags & SP_OBJECT_WRITE_EXT) {
286
353
        if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
287
 
            repr = sp_repr_new("svg:path");
 
354
            Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
 
355
            repr = xml_doc->createElement("svg:path");
288
356
        }
289
357
 
290
358
        sp_repr_set_svg_double(repr, "sodipodi:cx", ellipse->cx.computed);
351
419
}
352
420
 
353
421
static void
354
 
sp_ellipse_init(SPEllipse *ellipse)
 
422
sp_ellipse_init(SPEllipse */*ellipse*/)
355
423
{
356
424
    /* Nothing special */
357
425
}
376
444
    ellipse = SP_GENERICELLIPSE(object);
377
445
 
378
446
    if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
379
 
        repr = sp_repr_new("svg:ellipse");
 
447
        Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
 
448
        repr = xml_doc->createElement("svg:ellipse");
380
449
    }
381
450
 
382
451
    sp_repr_set_svg_double(repr, "cx", ellipse->cx.computed);
425
494
    }
426
495
}
427
496
 
428
 
static gchar *sp_ellipse_description(SPItem *item)
 
497
static gchar *sp_ellipse_description(SPItem */*item*/)
429
498
{
430
499
    return g_strdup(_("<b>Ellipse</b>"));
431
500
}
499
568
}
500
569
 
501
570
static void
502
 
sp_circle_init(SPCircle *circle)
 
571
sp_circle_init(SPCircle */*circle*/)
503
572
{
504
573
    /* Nothing special */
505
574
}
523
592
    ellipse = SP_GENERICELLIPSE(object);
524
593
 
525
594
    if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
526
 
        repr = sp_repr_new("svg:circle");
 
595
        Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
 
596
        repr = xml_doc->createElement("svg:circle");
527
597
    }
528
598
 
529
599
    sp_repr_set_svg_double(repr, "cx", ellipse->cx.computed);
566
636
    }
567
637
}
568
638
 
569
 
static gchar *sp_circle_description(SPItem *item)
 
639
static gchar *sp_circle_description(SPItem */*item*/)
570
640
{
571
641
    return g_strdup(_("<b>Circle</b>"));
572
642
}
624
694
}
625
695
 
626
696
static void
627
 
sp_arc_init(SPArc *arc)
 
697
sp_arc_init(SPArc */*arc*/)
628
698
{
629
699
    /* Nothing special */
630
700
}
658
728
static gboolean
659
729
sp_arc_set_elliptical_path_attribute(SPArc *arc, Inkscape::XML::Node *repr)
660
730
{
661
 
    gint fa, fs;
662
 
    gdouble  dt;
663
 
    Inkscape::SVGOStringStream os;
664
 
 
665
731
    SPGenericEllipse *ge = SP_GENERICELLIPSE(arc);
666
732
 
 
733
    Inkscape::SVG::PathString str;
 
734
 
667
735
    NR::Point p1 = sp_arc_get_xy(arc, ge->start);
668
736
    NR::Point p2 = sp_arc_get_xy(arc, ge->end);
669
 
 
670
 
    dt = fmod(ge->end - ge->start, SP_2PI);
 
737
    double rx = ge->rx.computed;
 
738
    double ry = ge->ry.computed;
 
739
 
 
740
    str.moveTo(p1);
 
741
 
 
742
    double dt = fmod(ge->end - ge->start, SP_2PI);
671
743
    if (fabs(dt) < 1e-6) {
672
744
        NR::Point ph = sp_arc_get_xy(arc, (ge->start + ge->end) / 2.0);
673
 
        os << "M " << p1[NR::X] << " " <<  p1[NR::Y]
674
 
           << " A " << ge->rx.computed << " " << ge->ry.computed
675
 
           << " 0 1 1 " << " " << ph[NR::X] << "," << ph[NR::Y]
676
 
           << " A " << ge->rx.computed << " " << ge->ry.computed
677
 
           << " 0 1 1 " << " " << p2[NR::X] << " " << p2[NR::Y] << " z";
 
745
        str.arcTo(rx, ry, 0, true, true, ph)
 
746
           .arcTo(rx, ry, 0, true, true, p2)
 
747
           .closePath();
678
748
    } else {
679
 
        fa = (fabs(dt) > M_PI) ? 1 : 0;
680
 
        fs = (dt > 0) ? 1 : 0;
681
 
#ifdef ARC_VERBOSE
682
 
        g_print("start:%g end:%g fa=%d fs=%d\n", ge->start, ge->end, fa, fs);
683
 
#endif
 
749
        bool fa = (fabs(dt) > M_PI);
 
750
        bool fs = (dt > 0);
 
751
        str.arcTo(rx, ry, 0, fa, fs, p2);
684
752
        if (ge->closed) {
685
 
            os << "M " << p1[NR::X] << "," << p1[NR::Y]
686
 
               << " A " << ge->rx.computed << "," << ge->ry.computed
687
 
               << " 0 " << fa << " " << fs << " " << p2[NR::X] << "," << p2[NR::Y]
688
 
               << " L " << ge->cx.computed << "," << ge->cy.computed << " z";
689
 
        } else {
690
 
            os << "M " << p1[NR::X] << "," << p1[NR::Y]
691
 
               << " A " << ge->rx.computed << "," << ge->ry.computed
692
 
               << " 0 " << fa << " " << fs << " " << p2[NR::X] << "," << p2[NR::Y];
693
 
 
 
753
            NR::Point center = NR::Point(ge->cx.computed, ge->cy.computed);
 
754
            str.lineTo(center).closePath();
694
755
        }
695
756
    }
696
 
    repr->setAttribute("d", os.str().c_str());
 
757
 
 
758
    repr->setAttribute("d", str.c_str());
697
759
    return true;
698
760
}
699
761
 
704
766
    SPArc *arc = SP_ARC(object);
705
767
 
706
768
    if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
707
 
        repr = sp_repr_new("svg:path");
 
769
        Inkscape::XML::Document *xml_doc = sp_document_repr_doc(SP_OBJECT_DOCUMENT(object));
 
770
        repr = xml_doc->createElement("svg:path");
708
771
    }
709
772
 
710
773
    if (flags & SP_OBJECT_WRITE_EXT) {