Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / sp-line.cpp
1 /*
2  * SVG <line> implementation
3  *
4  * Authors:
5  *   Lauris Kaplinski <lauris@kaplinski.com>
6  *   Abhishek Sharma
7  *   Jon A. Cruz <jon@joncruz.org>
8  *
9  * Copyright (C) 1999-2002 Lauris Kaplinski
10  *
11  * Released under GNU GPL, read the file 'COPYING' for more information
12  */
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
17 #include "attributes.h"
18 #include "style.h"
19 #include "sp-line.h"
20 #include "sp-guide.h"
21 #include "display/curve.h"
22 #include <glibmm/i18n.h>
23 #include <libnr/nr-matrix-fns.h>
24 #include <xml/repr.h>
25 #include "document.h"
26 #include "inkscape.h"
28 SPShapeClass * SPLineClass::static_parent_class = 0;
30 GType SPLine::sp_line_get_type(void)
31 {
32     static GType line_type = 0;
34     if (!line_type) {
35         GTypeInfo line_info = {
36             sizeof(SPLineClass),
37             NULL,       /* base_init */
38             NULL,       /* base_finalize */
39             (GClassInitFunc) SPLineClass::sp_line_class_init,
40             NULL,       /* klass_finalize */
41             NULL,       /* klass_data */
42             sizeof(SPLine),
43             16, /* n_preallocs */
44             (GInstanceInitFunc) init,
45             NULL,       /* value_table */
46         };
47         line_type = g_type_register_static(SP_TYPE_SHAPE, "SPLine", &line_info,(GTypeFlags)0);
48     }
49     return line_type;
50 }
52 void SPLineClass::sp_line_class_init(SPLineClass *klass)
53 {
54     SPLineClass::static_parent_class = (SPShapeClass *) g_type_class_ref(SP_TYPE_SHAPE);
56     SPObjectClass *sp_object_class = (SPObjectClass *) klass;
57     sp_object_class->build = SPLine::build;
58     sp_object_class->set = SPLine::set;
59     sp_object_class->write = SPLine::write;
61     SPItemClass *item_class = (SPItemClass *) klass;
62     item_class->description = SPLine::getDescription;
63     item_class->set_transform = SPLine::setTransform;
64     item_class->convert_to_guides = SPLine::convertToGuides;
66     sp_object_class->update = SPLine::update;
68     SPShapeClass *shape_class = (SPShapeClass *) klass;
69     shape_class->set_shape = SPLine::setShape;
70 }
72 void SPLine::init(SPLine * line)
73 {
74     line->x1.unset();
75     line->y1.unset();
76     line->x2.unset();
77     line->y2.unset();
78 }
81 void SPLine::build(SPObject * object, SPDocument * document, Inkscape::XML::Node * repr)
82 {
83     if (((SPObjectClass *) SPLineClass::static_parent_class)->build) {
84         ((SPObjectClass *) SPLineClass::static_parent_class)->build(object, document, repr);
85     }
87     object->readAttr( "x1" );
88     object->readAttr( "y1" );
89     object->readAttr( "x2" );
90     object->readAttr( "y2" );
91 }
93 void SPLine::set(SPObject *object, unsigned int key, const gchar *value)
94 {
95     SPLine * line = SP_LINE(object);
97     /* fixme: we should really collect updates */
99     switch (key) {
100         case SP_ATTR_X1:
101             line->x1.readOrUnset(value);
102             object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
103             break;
104         case SP_ATTR_Y1:
105             line->y1.readOrUnset(value);
106             object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
107             break;
108         case SP_ATTR_X2:
109             line->x2.readOrUnset(value);
110             object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
111             break;
112         case SP_ATTR_Y2:
113             line->y2.readOrUnset(value);
114             object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
115             break;
116         default:
117             if (((SPObjectClass *) SPLineClass::static_parent_class)->set) {
118                 ((SPObjectClass *) SPLineClass::static_parent_class)->set(object, key, value);
119             }
120             break;
121     }
124 void SPLine::update(SPObject *object, SPCtx *ctx, guint flags)
126     if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
127         SPLine *line = SP_LINE(object);
129         SPStyle const *style = object->style;
130         SPItemCtx const *ictx = (SPItemCtx const *) ctx;
131         double const w = (ictx->vp.x1 - ictx->vp.x0);
132         double const h = (ictx->vp.y1 - ictx->vp.y0);
133         double const em = style->font_size.computed;
134         double const ex = em * 0.5;  // fixme: get from pango or libnrtype.
135         line->x1.update(em, ex, w);
136         line->x2.update(em, ex, w);
137         line->y1.update(em, ex, h);
138         line->y2.update(em, ex, h);
140         ((SPShape *) object)->setShape();
141     }
143     if (((SPObjectClass *) SPLineClass::static_parent_class)->update) {
144         ((SPObjectClass *) SPLineClass::static_parent_class)->update(object, ctx, flags);
145     }
149 Inkscape::XML::Node * SPLine::write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
151     SPLine *line  = SP_LINE(object);
153     if ((flags & SP_OBJECT_WRITE_BUILD) && !repr) {
154         repr = xml_doc->createElement("svg:line");
155     }
157     if (repr != object->getRepr()) {
158         repr->mergeFrom(object->getRepr(), "id");
159     }
161     sp_repr_set_svg_double(repr, "x1", line->x1.computed);
162     sp_repr_set_svg_double(repr, "y1", line->y1.computed);
163     sp_repr_set_svg_double(repr, "x2", line->x2.computed);
164     sp_repr_set_svg_double(repr, "y2", line->y2.computed);
166     if (((SPObjectClass *) (SPLineClass::static_parent_class))->write) {
167         ((SPObjectClass *) (SPLineClass::static_parent_class))->write(object, xml_doc, repr, flags);
168     }
170     return repr;
173 gchar * SPLine::getDescription(SPItem */*item*/)
175     return g_strdup(_("<b>Line</b>"));
178 void SPLine::convertToGuides(SPItem *item)
180     SPLine *line = SP_LINE(item);
181     Geom::Point points[2];
183     Geom::Matrix const i2d(item->i2d_affine());
185     points[0] = Geom::Point(line->x1.computed, line->y1.computed)*i2d;
186     points[1] = Geom::Point(line->x2.computed, line->y2.computed)*i2d;
188     SPGuide::createSPGuide(inkscape_active_desktop(), points[0], points[1]);
191 Geom::Matrix SPLine::setTransform(SPItem *item, Geom::Matrix const &xform)
193     SPLine *line = SP_LINE(item);
194     Geom::Point points[2];
196     points[0] = Geom::Point(line->x1.computed, line->y1.computed);
197     points[1] = Geom::Point(line->x2.computed, line->y2.computed);
199     points[0] *= xform;
200     points[1] *= xform;
202     line->x1.computed = points[0][Geom::X];
203     line->y1.computed = points[0][Geom::Y];
204     line->x2.computed = points[1][Geom::X];
205     line->y2.computed = points[1][Geom::Y];
207     item->adjust_stroke(xform.descrim());
209     SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
211     return Geom::identity();
214 void SPLine::setShape(SPShape *shape)
216     SPLine *line = SP_LINE(shape);
218     SPCurve *c = new SPCurve();
220     c->moveto(line->x1.computed, line->y1.computed);
221     c->lineto(line->x2.computed, line->y2.computed);
223     shape->setCurveInsync(c, TRUE); // *_insync does not call update, avoiding infinite recursion when set_shape is called by update
225     c->unref();
228 /*
229   Local Variables:
230   mode:c++
231   c-file-style:"stroustrup"
232   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
233   indent-tabs-mode:nil
234   fill-column:99
235   End:
236 */
237 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :