sp-ellipse.cpp revision 0d7d0c5ccf9cf86ff11a88f614a44cc29136fe28
/*
* SVG <ellipse> and related implementations
*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Mitsuru Oka
* bulia byak <buliabyak@users.sf.net>
* Abhishek Sharma
*
* Copyright (C) 1999-2002 Lauris Kaplinski
* Copyright (C) 2000-2001 Ximian, Inc.
* Copyright (C) 2013 Tavmjong Bah
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include <glibmm.h>
#include "attributes.h"
#include "document.h"
#include "preferences.h"
#include "snap-candidate.h"
#include "sp-ellipse.h"
#include "style.h"
#include "svg/path-string.h"
#include "sp-factory.h"
namespace {
{
return ellipse;
}
{
return circle;
}
{
return arc;
}
}
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
: SPShape()
, start(0)
, _closed(true)
{
}
{
}
}
bool SPGenericEllipse::closed() {
return _closed;
}
{
// std::cout << "SPGenericEllipse::build: Entrance: " << this->type
// << " (" << g_quark_to_string(repr->code()) << ")" << std::endl;
switch ( type ) {
case SP_GENERIC_ELLIPSE_ARC:
this->readAttr("sodipodi:cx");
this->readAttr("sodipodi:cy");
this->readAttr("sodipodi:rx");
this->readAttr("sodipodi:ry");
this->readAttr("sodipodi:start");
this->readAttr("sodipodi:end");
this->readAttr("sodipodi:open");
break;
this->readAttr("cx");
this->readAttr("cy");
this->readAttr("r");
break;
this->readAttr("cx");
this->readAttr("cy");
this->readAttr("rx");
this->readAttr("ry");
break;
default:
}
}
{
// There are multiple ways to set internal cx, cy, rx, and ry (via SVG attributes or Sodipodi
// attributes) thus we don't want to unset them if a read fails (e.g., when we explicitly clear
// an attribute by setting it to NULL).
SVGLength t;
switch (key) {
case SP_ATTR_CX:
case SP_ATTR_SODIPODI_CX:
break;
case SP_ATTR_CY:
case SP_ATTR_SODIPODI_CY:
break;
case SP_ATTR_RX:
case SP_ATTR_SODIPODI_RX:
break;
case SP_ATTR_RY:
case SP_ATTR_SODIPODI_RY:
break;
case SP_ATTR_R:
}
break;
case SP_ATTR_SODIPODI_START:
if (value) {
} else {
this->start = 0;
}
break;
case SP_ATTR_SODIPODI_END:
if (value) {
} else {
}
break;
case SP_ATTR_SODIPODI_OPEN:
break;
default:
break;
}
}
{
// std::cout << "\nSPGenericEllipse::update: Entrance" << std::endl;
if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
this->set_shape();
}
// std::cout << "SPGenericEllipse::update: Exit\n" << std::endl;
}
Inkscape::XML::Node *SPGenericEllipse::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
{
// std::cout << "\nSPGenericEllipse::write: Entrance ("
// << (repr == NULL ? " NULL" : g_quark_to_string(repr->code()))
// << ")" << std::endl;
if (this->_isSlice() || hasPathEffect() ) {
} else {
}
// std::cout << " new_type: " << new_type << std::endl;
switch ( new_type ) {
case SP_GENERIC_ELLIPSE_ARC:
break;
break;
break;
default:
}
}
switch( new_type ) {
case SP_GENERIC_ELLIPSE_ARC:
break;
break;
break;
default:
}
// FIXME: The XML dialog won't update the element name. We need
// a notifyElementNameChanged callback added to the XML observers
// to trigger a refresh.
}
// std::cout << " type: " << g_quark_to_string( repr->code() ) << std::endl;
// std::cout << " cx: " << cx.computed
// << " cy: " << cy.computed
// << " rx: " << rx.computed
// << " ry: " << ry.computed << std::endl;
switch ( type ) {
case SP_GENERIC_ELLIPSE_ARC:
if (flags & SP_OBJECT_WRITE_EXT) {
// write start and end only if they are non-trivial; otherwise remove
if (this->_isSlice()) {
} else {
}
}
// write d=
this->set_elliptical_path_attribute(repr);
break;
break;
break;
default:
}
this->set_shape(); // evaluate SPCurve
// std::cout << "SPGenericEllipse::write: Exit: " << g_quark_to_string(repr->code()) << "\n" << std::endl;
return repr;
}
const char *SPGenericEllipse::displayName() const
{
switch ( type ) {
case SP_GENERIC_ELLIPSE_ARC:
if (this->_isSlice()) {
if (this->_closed) {
return _("Segment");
} else {
return _("Arc");
}
} else {
return _("Ellipse");
}
return _("Circle");
return _("Ellipse");
default:
return "Unknown ellipse: ERROR";
}
return ("Shouldn't be here");
}
// Create path for rendering shape on screen
void SPGenericEllipse::set_shape()
{
// std::cout << "SPGenericEllipse::set_shape: Entrance" << std::endl;
if (hasBrokenPathEffect()) {
g_warning("The ellipse shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as ellipse will remove the bad LPE");
// unconditionally read the curve from d, if any, to preserve appearance
}
return;
}
return;
}
this->normalize();
// For simplicity, we use a circle with center (0, 0) and radius 1 for our calculations.
if (!this->_isSlice()) {
start = 0.0;
}
arc = circle.arc(Geom::Point::polar(start + seg*incr), Geom::Point::polar(start + (seg + 0.5)*incr), Geom::Point::polar(start + (seg + 1.0)*incr));
delete arc;
}
}
if (this->_closed) {
} else {
}
// gchar *str = sp_svg_write_path(curve->get_pathvector());
// std::cout << " path: " << str << std::endl;
// g_free(str);
// Stretching / moving the calculated shape to fit the actual dimensions.
Geom::Affine aff = Geom::Scale(rx.computed, ry.computed) * Geom::Translate(cx.computed, cy.computed);
/* Reset the shape's curve to the "original_curve"
* This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
this->setCurveBeforeLPE(curve);
if (hasPathEffect() && pathEffectsEnabled()) {
if (success) {
}
}
// std::cout << "SPGenericEllipse::set_shape: Exit" << std::endl;
}
{
// Allow live effects
if (hasPathEffect() && pathEffectsEnabled()) {
return xform;
}
/* Calculate ellipse start in parent coords. */
/* This function takes care of translation and scaling, we return whatever parts we can't
handle. */
if (sw > 1e-9) {
} else {
ret[0] = 1.0;
}
if (sh > 1e-9) {
} else {
}
}
}
/* Find start in item coords */
this->set_shape();
// Adjust stroke width
// Adjust pattern fill
// Adjust gradient fill
return ret;
}
void SPGenericEllipse::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const
{
// CPPIFY: is this call necessary?
const_cast<SPGenericEllipse*>(this)->normalize();
// Snap to the 4 quadrant points of the ellipse, but only if the arc
// spans far enough to include them
p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_ELLIPSE_QUADRANT_POINT, Inkscape::SNAPTARGET_ELLIPSE_QUADRANT_POINT));
}
}
}
// Add the centre, if we have a closed slice or when explicitly asked for
p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP));
}
p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT));
}
// And if we have a slice, also snap to the endpoints
// Add the start point, if it's not coincident with a quadrant point
p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP));
}
// Add the end point, if it's not coincident with a quadrant point
p.push_back(Inkscape::SnapCandidatePoint(pt, Inkscape::SNAPSOURCE_NODE_CUSP, Inkscape::SNAPTARGET_NODE_CUSP));
}
}
}
{
if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) {
this->set_shape();
}
}
{
this->set_shape();
if (write) {
} else {
}
}
}
void SPGenericEllipse::normalize()
{
}
{
return Geom::Point::polar(arg) * Geom::Scale(rx.computed, ry.computed) * Geom::Translate(cx.computed, cy.computed);
}
/*
* set_elliptical_path_attribute:
*
* Convert center to endpoint parameterization and set it to repr.
*
* See SVG 1.0 Specification W3C Recommendation
* ``F.6 Ellptical arc implementation notes'' for more detail.
*/
{
// Make sure our pathvector is up to date.
this->set_shape();
g_free(d);
} else {
}
return true;
}
{
// those pref values are in degrees, while we want radians
this->start = Geom::Angle::from_degrees(prefs->getDouble("/tools/shapes/arc/start", 0.0)).radians0();
}
}
}
bool SPGenericEllipse::_isSlice() const
{
}
/*
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:fileencoding=utf-8 :