// SPDX-License-Identifier: GPL-2.0-or-later /** \file grid.cpp A plug-in to add a grid creation effect into Inkscape. */ /* * Copyright (C) 2004-2005 Ted Gould * Copyright (C) 2007 MenTaLguY * Abhishek Sharma * * Released under GNU GPL v2+, read the file 'COPYING' for more information. */ #include #include #include #include "desktop.h" #include "document.h" #include "layer-manager.h" #include "selection.h" #include "2geom/geom.h" #include "svg/path-string.h" #include "extension/effect.h" #include "extension/system.h" #include "util/units.h" #include "grid.h" namespace Inkscape { namespace Extension { namespace Internal { /** \brief A function to allocated anything -- just an example here \param module Unused \return Whether the load was successful */ bool Grid::load (Inkscape::Extension::Extension */*module*/) { // std::cout << "Hey, I'm Grid, I'm loading!" << std::endl; return TRUE; } namespace { Glib::ustring build_lines(Geom::Rect bounding_area, Geom::Point const &offset, Geom::Point const &spacing) { Geom::Point point_offset(0.0, 0.0); SVG::PathString path_data; for ( int axis = Geom::X ; axis <= Geom::Y ; ++axis ) { point_offset[axis] = offset[axis]; for (Geom::Point start_point = bounding_area.min(); start_point[axis] + offset[axis] <= (bounding_area.max())[axis]; start_point[axis] += spacing[axis]) { Geom::Point end_point = start_point; end_point[1-axis] = (bounding_area.max())[1-axis]; path_data.moveTo(start_point + point_offset) .lineTo(end_point + point_offset); } } // std::cout << "Path data:" << path_data.c_str() << std::endl; return path_data; } } // namespace /** \brief This actually draws the grid. \param module The effect that was called (unused) \param document What should be edited. */ void Grid::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *view, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) { auto desktop = dynamic_cast(view); Inkscape::Selection *selection = desktop->selection; SPDocument *doc = desktop->doc(); Geom::Rect bounding_area = Geom::Rect(Geom::Point(0,0), Geom::Point(100,100)); if (selection->isEmpty()) { /* get page size */ if (auto bounds = doc->preferredBounds()) { bounding_area = *bounds; } } else { if (auto bounds = selection->visualBounds()) { bounding_area = *bounds; } Geom::Rect temprec = bounding_area * desktop->doc2dt(); bounding_area = temprec; } double scale = doc->getDocumentScale().inverse()[Geom::X]; bounding_area *= Geom::Scale(scale); Geom::Point spacings( scale * module->get_param_float("xspacing"), scale * module->get_param_float("yspacing") ); gdouble line_width = scale * module->get_param_float("lineWidth"); Geom::Point offsets( scale * module->get_param_float("xoffset"), scale * module->get_param_float("yoffset") ); Glib::ustring path_data(""); path_data = build_lines(bounding_area, offsets, spacings); Inkscape::XML::Document * xml_doc = doc->getReprDoc(); //XML Tree being used directly here while it shouldn't be. Inkscape::XML::Node * current_layer = desktop->layerManager().currentLayer()->getRepr(); Inkscape::XML::Node * path = xml_doc->createElement("svg:path"); path->setAttribute("d", path_data); std::ostringstream stringstream; stringstream << "fill:none;stroke:#000000;stroke-width:" << line_width << "px"; path->setAttribute("style", stringstream.str()); current_layer->appendChild(path); Inkscape::GC::release(path); } /** \brief A class to make an adjustment that uses Extension params */ class PrefAdjustment : public Gtk::Adjustment { /** Extension that this relates to */ Inkscape::Extension::Extension * _ext; /** The string which represents the parameter */ char * _pref; public: /** \brief Make the adjustment using an extension and the string describing the parameter. */ PrefAdjustment(Inkscape::Extension::Extension * ext, char * pref) : Gtk::Adjustment(0.0, 0.0, 10.0, 0.1), _ext(ext), _pref(pref) { this->set_value(_ext->get_param_float(_pref)); this->signal_value_changed().connect(sigc::mem_fun(this, &PrefAdjustment::val_changed)); return; }; void val_changed (); }; /* class PrefAdjustment */ /** \brief A function to respond to the value_changed signal from the adjustment. This function just grabs the value from the adjustment and writes it to the parameter. Very simple, but yet beautiful. */ void PrefAdjustment::val_changed () { // std::cout << "Value Changed to: " << this->get_value() << std::endl; _ext->set_param_float(_pref, this->get_value()); return; } /** \brief A function to get the preferences for the grid \param module Module which holds the params \param view Unused today - may get style information in the future. Uses AutoGUI for creating the GUI. */ Gtk::Widget * Grid::prefs_effect(Inkscape::Extension::Effect *module, Inkscape::UI::View::View * view, sigc::signal * changeSignal, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/) { SPDocument * current_document = view->doc(); auto selected = ((SPDesktop *) view)->getSelection()->items(); Inkscape::XML::Node * first_select = nullptr; if (!selected.empty()) { first_select = selected.front()->getRepr(); } return module->autogui(current_document, first_select, changeSignal); } #include "clear-n_.h" void Grid::init () { // clang-format off Inkscape::Extension::build_from_mem( "\n" "" N_("Grid") "\n" "org.inkscape.effect.grid\n" "1.0\n" "10.0\n" "10.0\n" "0.0\n" "0.0\n" "\n" "all\n" "\n" "\n" "\n" "\n" "\n" "" N_("Draw a path which is a grid") "\n" "\n" "\n", new Grid()); // clang-format on return; } }; /* namespace Internal */ }; /* namespace Extension */ }; /* namespace Inkscape */ /* 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 :