canvas-grid.cpp revision 208e5a33acc4a8ad9d8c0488f047c260346f1258
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan#define INKSCAPE_CANVAS_GRID_C
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan/*
5779b9adde0a838db067a3d76f3124eeb8e86d4cJason Vincent *
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan * Copyright (C) Johan Engelen 2006-2007 <johan@shouraizou.nl>
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos * Copyright (C) Lauris Kaplinski 2000
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos *
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos */
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos#include "sp-canvas-util.h"
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos#include "display-forward.h"
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos#include <libnr/nr-pixops.h>
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos#include "desktop-handles.h"
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos#include "helper/units.h"
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos#include "svg/svg-color.h"
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos#include "xml/node-event-vector.h"
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos#include "sp-object.h"
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos#include "sp-namedview.h"
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos#include "inkscape.h"
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos#include "desktop.h"
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan#include "../document.h"
ab359738f77f6061fd76982ba391ae52e07b0203Paul Bryan
f56ff38befd2d32c4d47af7794303ee7c3a36f94Andi Egloff#include "canvas-grid.h"
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan#include "canvas-axonomgrid.h"
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienlenamespace Inkscape {
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle#define DEFAULTGRIDCOLOR 0x0000FF20
99d48ef2e4a3c05cde78b89088fad201080e88f0Laszlo Hordos#define DEFAULTGRIDEMPCOLOR 0x0000FF40
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo Hordos
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienlestatic gchar const *const grid_name[] = {
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan N_("Rectangular grid"),
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos N_("Axonometric grid")
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle};
10a9be648c010204b8ba63b283aa177749227e11Paul Bryanstatic gchar const *const grid_svgname[] = {
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan "xygrid",
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan "axonomgrid"
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle};
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo Hordos
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan// ##########################################################
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan// Grid CanvasItem
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienlestatic void grid_canvasitem_class_init (GridCanvasItemClass *klass);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienlestatic void grid_canvasitem_init (GridCanvasItem *grid);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienlestatic void grid_canvasitem_destroy (GtkObject *object);
5779b9adde0a838db067a3d76f3124eeb8e86d4cJason Vincent
5779b9adde0a838db067a3d76f3124eeb8e86d4cJason Vincentstatic void grid_canvasitem_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags);
5779b9adde0a838db067a3d76f3124eeb8e86d4cJason Vincentstatic void grid_canvasitem_render (SPCanvasItem *item, SPCanvasBuf *buf);
5779b9adde0a838db067a3d76f3124eeb8e86d4cJason Vincent
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloffstatic SPCanvasItemClass * parent_class;
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
10a9be648c010204b8ba63b283aa177749227e11Paul BryanGtkType
90e23b56c7ebf9dffe7ad87f1031103d2b49c08ePaul Bryangrid_canvasitem_get_type (void)
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan{
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan static GtkType grid_canvasitem_type = 0;
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloff if (!grid_canvasitem_type) {
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle GtkTypeInfo grid_canvasitem_info = {
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan "GridCanvasItem",
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle sizeof (GridCanvasItem),
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle sizeof (GridCanvasItemClass),
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle (GtkClassInitFunc) grid_canvasitem_class_init,
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle (GtkObjectInitFunc) grid_canvasitem_init,
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle NULL, NULL,
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle (GtkClassInitFunc) NULL
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle };
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall grid_canvasitem_type = gtk_type_unique (sp_canvas_item_get_type (), &grid_canvasitem_info);
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos }
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos return grid_canvasitem_type;
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos}
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
10a9be648c010204b8ba63b283aa177749227e11Paul Bryanstatic void
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloffgrid_canvasitem_class_init (GridCanvasItemClass *klass)
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan{
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan GtkObjectClass *object_class;
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle SPCanvasItemClass *item_class;
9697d1ddb3900b1f7f16af9e3be0d1bb34c1f965Paul Bryan
47196c962e3caf7cdf7ea5d00ccdefc9f208bdceLaszlo Hordos object_class = (GtkObjectClass *) klass;
47196c962e3caf7cdf7ea5d00ccdefc9f208bdceLaszlo Hordos item_class = (SPCanvasItemClass *) klass;
47196c962e3caf7cdf7ea5d00ccdefc9f208bdceLaszlo Hordos
376d1bf8f8ca562eecccbf0a0d34aa7c7352e152Laszlo Hordos parent_class = (SPCanvasItemClass*)gtk_type_class (sp_canvas_item_get_type ());
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall
90e23b56c7ebf9dffe7ad87f1031103d2b49c08ePaul Bryan object_class->destroy = grid_canvasitem_destroy;
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan item_class->update = grid_canvasitem_update;
90e23b56c7ebf9dffe7ad87f1031103d2b49c08ePaul Bryan item_class->render = grid_canvasitem_render;
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos}
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hallstatic void
10a9be648c010204b8ba63b283aa177749227e11Paul Bryangrid_canvasitem_init (GridCanvasItem *griditem)
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos{
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos griditem->grid = NULL;
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos}
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
10a9be648c010204b8ba63b283aa177749227e11Paul Bryanstatic void
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordosgrid_canvasitem_destroy (GtkObject *object)
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos{
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos g_return_if_fail (object != NULL);
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos g_return_if_fail (INKSCAPE_IS_GRID_CANVASITEM (object));
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos if (GTK_OBJECT_CLASS (parent_class)->destroy)
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloff}
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloff/**
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos*/
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordosstatic void
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordosgrid_canvasitem_render (SPCanvasItem * item, SPCanvasBuf * buf)
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo Hordos{
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo Hordos GridCanvasItem *gridcanvasitem = INKSCAPE_GRID_CANVASITEM (item);
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo Hordos
376d1bf8f8ca562eecccbf0a0d34aa7c7352e152Laszlo Hordos sp_canvas_prepare_buffer (buf);
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan if (gridcanvasitem->grid) gridcanvasitem->grid->Render(buf);
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan}
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
10a9be648c010204b8ba63b283aa177749227e11Paul Bryanstatic void
10a9be648c010204b8ba63b283aa177749227e11Paul Bryangrid_canvasitem_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags)
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloff{
376d1bf8f8ca562eecccbf0a0d34aa7c7352e152Laszlo Hordos GridCanvasItem *gridcanvasitem = INKSCAPE_GRID_CANVASITEM (item);
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo Hordos if (parent_class->update)
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloff (* parent_class->update) (item, affine, flags);
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloff
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle if (gridcanvasitem->grid) {
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle gridcanvasitem->grid->Update(affine, flags);
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle sp_canvas_request_redraw (item->canvas,
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller -1000000, -1000000,
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller 1000000, 1000000);
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller item->x1 = item->y1 = -1000000;
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall item->x2 = item->y2 = 1000000;
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan }
376d1bf8f8ca562eecccbf0a0d34aa7c7352e152Laszlo Hordos}
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller// ##########################################################
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller// CanvasGrid
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloff
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo Hordos static Inkscape::XML::NodeEventVector const _repr_events = {
0901148a508a9c433851a650cd8eb52899d1222bLaszlo Hordos NULL, /* child_added */
0901148a508a9c433851a650cd8eb52899d1222bLaszlo Hordos NULL, /* child_removed */
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller CanvasGrid::on_repr_attr_changed,
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller NULL, /* content_changed */
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller NULL /* order_changed */
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller };
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan MillerCanvasGrid::CanvasGrid(SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument *in_doc)
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller{
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller repr = in_repr;
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller doc = in_doc;
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle if (repr) {
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle repr->addListener (&_repr_events, this);
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle }
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo Hordos
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo Hordos namedview = nv;
376d1bf8f8ca562eecccbf0a0d34aa7c7352e152Laszlo Hordos canvasitems = NULL;
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo Hordos}
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo Hordos
9c8c2c05a3d08f94d29b4a42b8a0506a4e97e4faLaszlo HordosCanvasGrid::~CanvasGrid()
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan{
376d1bf8f8ca562eecccbf0a0d34aa7c7352e152Laszlo Hordos if (repr) {
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos repr->removeListenerByData (this);
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall }
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos while (canvasitems) {
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan gtk_object_destroy(GTK_OBJECT(canvasitems->data));
376d1bf8f8ca562eecccbf0a0d34aa7c7352e152Laszlo Hordos canvasitems = g_slist_remove(canvasitems, canvasitems->data);
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos }
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos}
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordoschar const *
2ae41f94c30465830758177491494f918a7a79bcLaszlo HordosCanvasGrid::getName(GridType type)
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan{
376d1bf8f8ca562eecccbf0a0d34aa7c7352e152Laszlo Hordos return _(grid_name[type]);
47196c962e3caf7cdf7ea5d00ccdefc9f208bdceLaszlo Hordos}
376d1bf8f8ca562eecccbf0a0d34aa7c7352e152Laszlo Hordos
47196c962e3caf7cdf7ea5d00ccdefc9f208bdceLaszlo Hordoschar const *
10a9be648c010204b8ba63b283aa177749227e11Paul BryanCanvasGrid::getSVGName(GridType type)
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan{
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan return grid_svgname[type];
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle}
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle
dd291c383b4490ed77e47d65b4c52595d915f802Chad KienleGridType
dd291c383b4490ed77e47d65b4c52595d915f802Chad KienleCanvasGrid::getGridTypeFromSVGName(char const *typestr)
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle{
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle if (!typestr) return GRID_RECTANGULAR;
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle gint t = 0;
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle for (t = GRID_MAXTYPENR; t >= 0; t--) { //this automatically defaults to grid0 which is rectangular grid
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle if (!strcmp(typestr, grid_svgname[t])) break;
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller }
2aa8de21e6cca211bdb436c58886b60f4d32d073Brendan Miller return (GridType) t;
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle}
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle
dd291c383b4490ed77e47d65b4c52595d915f802Chad KienleGridType
dd291c383b4490ed77e47d65b4c52595d915f802Chad KienleCanvasGrid::getGridTypeFromName(char const *typestr)
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle{
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle if (!typestr) return GRID_RECTANGULAR;
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle gint t = 0;
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle for (t = GRID_MAXTYPENR; t >= 0; t--) { //this automatically defaults to grid0 which is rectangular grid
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle if (!strcmp(typestr, _(grid_name[t]))) break;
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle }
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle return (GridType) t;
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle}
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle
dd291c383b4490ed77e47d65b4c52595d915f802Chad Kienle
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloff/*
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan* writes an <inkscape:grid> child to repr.
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan*/
376d1bf8f8ca562eecccbf0a0d34aa7c7352e152Laszlo Hordosvoid
10a9be648c010204b8ba63b283aa177749227e11Paul BryanCanvasGrid::writeNewGridToRepr(Inkscape::XML::Node * repr, SPDocument * doc, GridType gridtype)
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan{
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan if (!repr) return;
90e23b56c7ebf9dffe7ad87f1031103d2b49c08ePaul Bryan if (gridtype > GRID_MAXTYPENR) return;
90e23b56c7ebf9dffe7ad87f1031103d2b49c08ePaul Bryan
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan // first create the child xml node, then hook it to repr. This order is important, to not set off listeners to repr before the new node is complete.
9697d1ddb3900b1f7f16af9e3be0d1bb34c1f965Paul Bryan
376d1bf8f8ca562eecccbf0a0d34aa7c7352e152Laszlo Hordos Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
9697d1ddb3900b1f7f16af9e3be0d1bb34c1f965Paul Bryan Inkscape::XML::Node *newnode;
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan newnode = xml_doc->createElement("inkscape:grid");
90e23b56c7ebf9dffe7ad87f1031103d2b49c08ePaul Bryan newnode->setAttribute("type", getSVGName(gridtype));
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan repr->appendChild(newnode);
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan// Inkscape::GC::release(repr); FIX THIS. THIS SHOULD BE HERE!!!
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan sp_document_done(doc, SP_VERB_DIALOG_NAMEDVIEW, _("Create new grid"));
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan}
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan/*
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos* Creates a new CanvasGrid object of type gridtype
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos*/
88f2d7061bb42999901dcff81c37089b000d32e0Paul BryanCanvasGrid*
88f2d7061bb42999901dcff81c37089b000d32e0Paul BryanCanvasGrid::NewGrid(SPNamedView * nv, Inkscape::XML::Node * repr, SPDocument * doc, GridType gridtype)
ab359738f77f6061fd76982ba391ae52e07b0203Paul Bryan{
2ae41f94c30465830758177491494f918a7a79bcLaszlo Hordos if (!repr) return NULL;
0da1e22d2b01edcea9b1b42072454ef841f17bfaPaul Bryan if (!doc) {
0da1e22d2b01edcea9b1b42072454ef841f17bfaPaul Bryan g_error("CanvasGrid::NewGrid - doc==NULL");
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan return NULL;
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan }
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
88f2d7061bb42999901dcff81c37089b000d32e0Paul Bryan switch (gridtype) {
88f2d7061bb42999901dcff81c37089b000d32e0Paul Bryan case GRID_RECTANGULAR:
88f2d7061bb42999901dcff81c37089b000d32e0Paul Bryan return (CanvasGrid*) new CanvasXYGrid(nv, repr, doc);
90e23b56c7ebf9dffe7ad87f1031103d2b49c08ePaul Bryan case GRID_AXONOMETRIC:
90e23b56c7ebf9dffe7ad87f1031103d2b49c08ePaul Bryan return (CanvasGrid*) new CanvasAxonomGrid(nv, repr, doc);
90e23b56c7ebf9dffe7ad87f1031103d2b49c08ePaul Bryan }
90e23b56c7ebf9dffe7ad87f1031103d2b49c08ePaul Bryan
0da1e22d2b01edcea9b1b42072454ef841f17bfaPaul Bryan return NULL;
0da1e22d2b01edcea9b1b42072454ef841f17bfaPaul Bryan}
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall
4b93fff6cbed4e2ae34e954b9b9bd4f318d34cd4Andi Egloff/**
4b93fff6cbed4e2ae34e954b9b9bd4f318d34cd4Andi Egloff* creates a new grid canvasitem for the SPDesktop given as parameter. Keeps a link to this canvasitem in the canvasitems list.
47196c962e3caf7cdf7ea5d00ccdefc9f208bdceLaszlo Hordos*/
4b93fff6cbed4e2ae34e954b9b9bd4f318d34cd4Andi EgloffGridCanvasItem *
4b93fff6cbed4e2ae34e954b9b9bd4f318d34cd4Andi EgloffCanvasGrid::createCanvasItem(SPDesktop * desktop)
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall{
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall if (!desktop) return NULL;
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall //Johan: I think for multiple desktops it is best if each has their own canvasitem, but share the same CanvasGrid object; that is what this function is for.
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall // check if there is already a canvasitem on this desktop linking to this grid
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall for (GSList *l = canvasitems; l != NULL; l = l->next) {
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall if ( sp_desktop_gridgroup(desktop) == SP_CANVAS_GROUP(SP_CANVAS_ITEM(l->data)->parent) ) {
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall return NULL;
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall }
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall }
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall GridCanvasItem * item = INKSCAPE_GRID_CANVASITEM( sp_canvas_item_new(sp_desktop_gridgroup(desktop), INKSCAPE_TYPE_GRID_CANVASITEM, NULL) );
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall item->grid = this;
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall sp_canvas_item_show(SP_CANVAS_ITEM(item));
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall gtk_object_ref(GTK_OBJECT(item)); // since we're keeping a link to this item, we need to bump up the ref count
47196c962e3caf7cdf7ea5d00ccdefc9f208bdceLaszlo Hordos canvasitems = g_slist_prepend(canvasitems, item);
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall return item;
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall}
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloffvoid
88f2d7061bb42999901dcff81c37089b000d32e0Paul BryanCanvasGrid::on_repr_attr_changed(Inkscape::XML::Node *repr, gchar const *key, gchar const *oldval, gchar const *newval, bool is_interactive, void *data)
88f2d7061bb42999901dcff81c37089b000d32e0Paul Bryan{
93f72edb164ef872eab6e4d482baa186a0dd6c62Andi Egloff if (!data)
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall return;
4b93fff6cbed4e2ae34e954b9b9bd4f318d34cd4Andi Egloff
4b93fff6cbed4e2ae34e954b9b9bd4f318d34cd4Andi Egloff ((CanvasGrid*) data)->onReprAttrChanged(repr, key, oldval, newval, is_interactive);
47196c962e3caf7cdf7ea5d00ccdefc9f208bdceLaszlo Hordos}
4b93fff6cbed4e2ae34e954b9b9bd4f318d34cd4Andi Egloff
7483266ec82ab642b8991a17132b83b6b5d72c3dTravis Hall
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle// ##########################################################
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle// CanvasXYGrid
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle
5c6780831f7f32502f025e2e795378ae5712dfffchad.kienle
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle/**
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle* "attach_all" function
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle* A DIRECT COPY-PASTE FROM DOCUMENT-PROPERTIES.CPP TO QUICKLY GET RESULTS
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle*
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle * Helper function that attachs widgets in a 3xn table. The widgets come in an
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle * array that has two entries per table row. The two entries code for four
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle * possible cases: (0,0) means insert space in first column; (0, non-0) means
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle * widget in columns 2-3; (non-0, 0) means label in columns 1-3; and
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle * (non-0, non-0) means two widgets in columns 2 and 3.
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle**/
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle#define SPACE_SIZE_X 15
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle#define SPACE_SIZE_Y 10
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienlestatic inline void
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienleattach_all(Gtk::Table &table, Gtk::Widget const *const arr[], unsigned size, int start = 0)
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle{
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle for (unsigned i=0, r=start; i<size/sizeof(Gtk::Widget*); i+=2) {
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle if (arr[i] && arr[i+1]) {
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle table.attach (const_cast<Gtk::Widget&>(*arr[i]), 1, 2, r, r+1,
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 2, 3, r, r+1,
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle } else {
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle if (arr[i+1]) {
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle table.attach (const_cast<Gtk::Widget&>(*arr[i+1]), 1, 3, r, r+1,
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle } else if (arr[i]) {
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle Gtk::Label& label = reinterpret_cast<Gtk::Label&> (const_cast<Gtk::Widget&>(*arr[i]));
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle label.set_alignment (0.0);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle table.attach (label, 0, 3, r, r+1,
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle Gtk::FILL|Gtk::EXPAND, (Gtk::AttachOptions)0,0,0);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle } else {
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle Gtk::HBox *space = manage (new Gtk::HBox);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle space->set_size_request (SPACE_SIZE_X, SPACE_SIZE_Y);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle table.attach (*space, 0, 1, r, r+1,
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle (Gtk::AttachOptions)0, (Gtk::AttachOptions)0,0,0);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle }
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle }
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle ++r;
03f0437b30a5f4e8c85a5da94eadfa1f8faca90dBrendan Miller }
03f0437b30a5f4e8c85a5da94eadfa1f8faca90dBrendan Miller}
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienleCanvasXYGrid::CanvasXYGrid (SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument * in_doc)
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle : CanvasGrid(nv, in_repr, in_doc), table(1, 1)
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle{
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle origin[NR::X] = origin[NR::Y] = 0.0;
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle color = DEFAULTGRIDCOLOR;
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle empcolor = DEFAULTGRIDEMPCOLOR;
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle empspacing = 5;
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle spacing[NR::X] = spacing[NR::Y] = 1.0;
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle gridunit = &sp_unit_get_by_id(SP_UNIT_PX);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle render_dotted = false;
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle snapper = new CanvasXYGridSnapper(this, namedview, 0);
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle // initialize widgets:
0d225a5b73f6420cb2afb27337f53e9772d8e610chad.kienle vbox.set_border_width(2);
10a9be648c010204b8ba63b283aa177749227e11Paul Bryan table.set_spacings(2);
vbox.pack_start(table, false, false, 0);
_rumg.init (_("Grid _units:"), "units", _wr, repr, doc);
_rsu_ox.init (_("_Origin X:"), _("X coordinate of grid origin"),
"originx", _rumg, _wr, repr, doc);
_rsu_oy.init (_("O_rigin Y:"), _("Y coordinate of grid origin"),
"originy", _rumg, _wr, repr, doc);
_rsu_sx.init (_("Spacing _X:"), _("Distance between vertical grid lines"),
"spacingx", _rumg, _wr, repr, doc);
_rsu_sy.init (_("Spacing _Y:"), _("Distance between horizontal grid lines"),
"spacingy", _rumg, _wr, repr, doc);
_rcp_gcol.init (_("Grid line _color:"), _("Grid line color"),
_("Color of grid lines"), "color", "opacity", _wr, repr, doc);
_rcp_gmcol.init (_("Ma_jor grid line color:"), _("Major grid line color"),
_("Color of the major (highlighted) grid lines"),
"empcolor", "empopacity", _wr, repr, doc);
_rsi.init (_("_Major grid line every:"), _("lines"), "empspacing", _wr, repr, doc);
_rcb_dotted.init ( _("_Show dots instead of lines"),
_("If set, displays dots at gridpoints instead of gridlines"),
"dotted", _wr, false, repr, doc);
Gtk::Widget const *const widget_array[] = {
_rumg._label, _rumg._sel,
0, _rsu_ox.getSU(),
0, _rsu_oy.getSU(),
0, _rsu_sx.getSU(),
0, _rsu_sy.getSU(),
_rcp_gcol._label, _rcp_gcol._cp,
0, 0,
_rcp_gmcol._label, _rcp_gmcol._cp,
_rsi._label, &_rsi._hbox,
0, _rcb_dotted._button,
};
attach_all (table, widget_array, sizeof(widget_array));
vbox.show();
if (repr) readRepr();
updateWidgets();
}
CanvasXYGrid::~CanvasXYGrid ()
{
if (snapper) delete snapper;
}
/* fixme: Collect all these length parsing methods and think common sane API */
static gboolean
sp_nv_read_length(gchar const *str, guint base, gdouble *val, SPUnit const **unit)
{
if (!str) {
return FALSE;
}
gchar *u;
gdouble v = g_ascii_strtod(str, &u);
if (!u) {
return FALSE;
}
while (isspace(*u)) {
u += 1;
}
if (!*u) {
/* No unit specified - keep default */
*val = v;
return TRUE;
}
if (base & SP_UNIT_DEVICE) {
if (u[0] && u[1] && !isalnum(u[2]) && !strncmp(u, "px", 2)) {
*unit = &sp_unit_get_by_id(SP_UNIT_PX);
*val = v;
return TRUE;
}
}
if (base & SP_UNIT_ABSOLUTE) {
if (!strncmp(u, "pt", 2)) {
*unit = &sp_unit_get_by_id(SP_UNIT_PT);
} else if (!strncmp(u, "mm", 2)) {
*unit = &sp_unit_get_by_id(SP_UNIT_MM);
} else if (!strncmp(u, "cm", 2)) {
*unit = &sp_unit_get_by_id(SP_UNIT_CM);
} else if (!strncmp(u, "m", 1)) {
*unit = &sp_unit_get_by_id(SP_UNIT_M);
} else if (!strncmp(u, "in", 2)) {
*unit = &sp_unit_get_by_id(SP_UNIT_IN);
} else {
return FALSE;
}
*val = v;
return TRUE;
}
return FALSE;
}
static gboolean sp_nv_read_opacity(gchar const *str, guint32 *color)
{
if (!str) {
return FALSE;
}
gchar *u;
gdouble v = g_ascii_strtod(str, &u);
if (!u) {
return FALSE;
}
v = CLAMP(v, 0.0, 1.0);
*color = (*color & 0xffffff00) | (guint32) floor(v * 255.9999);
return TRUE;
}
/** If the passed scalar is invalid (<=0), then set the widget and the scalar
to use the given old value.
@param oldVal Old value to use if the new one is invalid.
@param pTarget The scalar to validate.
@param widget Widget associated with the scalar.
*/
static void validateScalar(double oldVal,
double* pTarget,
Inkscape::UI::Widget::RegisteredScalarUnit& widget)
{
// Avoid nullness.
if ( pTarget == NULL )
return;
// Invalid new value?
if ( *pTarget <= 0 ) {
// If the old value is somehow invalid as well, then default to 1.
if ( oldVal <= 0 )
oldVal = 1;
// Reset the scalar and associated widget to the old value.
*pTarget = oldVal;
widget.setValue( *pTarget);
} //if
} //validateScalar
/** If the passed int is invalid (<=0), then set the widget and the int
to use the given old value.
@param oldVal Old value to use if the new one is invalid.
@param pTarget The int to validate.
@param widget Widget associated with the int.
*/
static void validateInt(gint oldVal,
gint* pTarget,
Inkscape::UI::Widget::RegisteredSuffixedInteger& widget)
{
// Avoid nullness.
if ( pTarget == NULL )
return;
// Invalid new value?
if ( *pTarget <= 0 ) {
// If the old value is somehow invalid as well, then default to 1.
if ( oldVal <= 0 )
oldVal = 1;
// Reset the int and associated widget to the old value.
*pTarget = oldVal;
widget.setValue( *pTarget);
} //if
} //validateInt
void
CanvasXYGrid::readRepr()
{
char buff[100];
gchar const *value;
if ( (value = repr->attribute("originx")) ) {
sp_nv_read_length(value, SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE, &origin[NR::X], &gridunit);
origin[NR::X] = sp_units_get_pixels(origin[NR::X], *(gridunit));
}
if ( (value = repr->attribute("originy")) ) {
sp_nv_read_length(value, SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE, &origin[NR::Y], &gridunit);
origin[NR::Y] = sp_units_get_pixels(origin[NR::Y], *(gridunit));
}
if ( (value = repr->attribute("spacingx")) ) {
double oldVal = spacing[NR::X];
sp_nv_read_length(value, SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE, &spacing[NR::X], &gridunit);
validateScalar( oldVal, &spacing[NR::X], _rsu_sx );
spacing[NR::X] = sp_units_get_pixels(spacing[NR::X], *(gridunit));
}
if ( (value = repr->attribute("spacingy")) ) {
double oldVal = spacing[NR::Y];
sp_nv_read_length(value, SP_UNIT_ABSOLUTE | SP_UNIT_DEVICE, &spacing[NR::Y], &gridunit);
validateScalar( oldVal, &spacing[NR::Y], _rsu_sy );
spacing[NR::Y] = sp_units_get_pixels(spacing[NR::Y], *(gridunit));
}
if ( (value = repr->attribute("color")) ) {
color = (color & 0xff) | sp_svg_read_color(value, color);
}
if ( (value = repr->attribute("empcolor")) ) {
empcolor = (empcolor & 0xff) | sp_svg_read_color(value, empcolor);
}
if ( (value = repr->attribute("opacity")) ) {
sp_nv_read_opacity(value, &color);
}
if ( (value = repr->attribute("empopacity")) ) {
sp_nv_read_opacity(value, &empcolor);
}
if ( (value = repr->attribute("empspacing")) ) {
gint oldVal = empspacing;
empspacing = atoi(value);
validateInt( oldVal, &empspacing, _rsi );
}
if ( (value = repr->attribute("dotted")) ) {
render_dotted = (strcmp(value,"true") == 0);
}
for (GSList *l = canvasitems; l != NULL; l = l->next) {
sp_canvas_item_request_update ( SP_CANVAS_ITEM(l->data) );
}
return;
}
/**
* Called when XML node attribute changed; updates dialog widgets if change was not done by widgets themselves.
*/
void
CanvasXYGrid::onReprAttrChanged(Inkscape::XML::Node *repr, gchar const *key, gchar const *oldval, gchar const *newval, bool is_interactive)
{
readRepr();
if ( ! (_wr.isUpdating()) )
updateWidgets();
}
Gtk::Widget &
CanvasXYGrid::getWidget()
{
return vbox;
}
/**
* Update dialog widgets from object's values.
*/
void
CanvasXYGrid::updateWidgets()
{
if (_wr.isUpdating()) return;
_wr.setUpdating (true);
_rumg.setUnit (gridunit);
gdouble val;
val = origin[NR::X];
val = sp_pixels_get_units (val, *(gridunit));
_rsu_ox.setValue (val);
val = origin[NR::Y];
val = sp_pixels_get_units (val, *(gridunit));
_rsu_oy.setValue (val);
val = spacing[NR::X];
double gridx = sp_pixels_get_units (val, *(gridunit));
_rsu_sx.setValue (gridx);
val = spacing[NR::Y];
double gridy = sp_pixels_get_units (val, *(gridunit));
_rsu_sy.setValue (gridy);
_rcp_gcol.setRgba32 (color);
_rcp_gmcol.setRgba32 (empcolor);
_rsi.setValue (empspacing);
_wr.setUpdating (false);
return;
}
void
CanvasXYGrid::Update (NR::Matrix const &affine, unsigned int flags)
{
ow = origin * affine;
sw = spacing * affine;
sw -= NR::Point(affine[4], affine[5]);
for(int dim = 0; dim < 2; dim++) {
gint scaling_factor = empspacing;
if (scaling_factor <= 1)
scaling_factor = 5;
scaled[dim] = FALSE;
sw[dim] = fabs (sw[dim]);
while (sw[dim] < 8.0) {
scaled[dim] = TRUE;
sw[dim] *= scaling_factor;
/* First pass, go up to the major line spacing, then
keep increasing by two. */
scaling_factor = 2;
}
}
}
static void
grid_hline (SPCanvasBuf *buf, gint y, gint xs, gint xe, guint32 rgba)
{
if ((y >= buf->rect.y0) && (y < buf->rect.y1)) {
guint r, g, b, a;
gint x0, x1, x;
guchar *p;
r = NR_RGBA32_R (rgba);
g = NR_RGBA32_G (rgba);
b = NR_RGBA32_B (rgba);
a = NR_RGBA32_A (rgba);
x0 = MAX (buf->rect.x0, xs);
x1 = MIN (buf->rect.x1, xe + 1);
p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x0 - buf->rect.x0) * 3;
for (x = x0; x < x1; x++) {
p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
p += 3;
}
}
}
static void
grid_vline (SPCanvasBuf *buf, gint x, gint ys, gint ye, guint32 rgba)
{
if ((x >= buf->rect.x0) && (x < buf->rect.x1)) {
guint r, g, b, a;
gint y0, y1, y;
guchar *p;
r = NR_RGBA32_R(rgba);
g = NR_RGBA32_G (rgba);
b = NR_RGBA32_B (rgba);
a = NR_RGBA32_A (rgba);
y0 = MAX (buf->rect.y0, ys);
y1 = MIN (buf->rect.y1, ye + 1);
p = buf->buf + (y0 - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3;
for (y = y0; y < y1; y++) {
p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
p += buf->buf_rowstride;
}
}
}
static void
grid_dot (SPCanvasBuf *buf, gint x, gint y, guint32 rgba)
{
if ( (y >= buf->rect.y0) && (y < buf->rect.y1)
&& (x >= buf->rect.x0) && (x < buf->rect.x1) ) {
guint r, g, b, a;
guchar *p;
r = NR_RGBA32_R (rgba);
g = NR_RGBA32_G (rgba);
b = NR_RGBA32_B (rgba);
a = NR_RGBA32_A (rgba);
p = buf->buf + (y - buf->rect.y0) * buf->buf_rowstride + (x - buf->rect.x0) * 3;
p[0] = NR_COMPOSEN11_1111 (r, a, p[0]);
p[1] = NR_COMPOSEN11_1111 (g, a, p[1]);
p[2] = NR_COMPOSEN11_1111 (b, a, p[2]);
}
}
void
CanvasXYGrid::Render (SPCanvasBuf *buf)
{
gdouble const sxg = floor ((buf->rect.x0 - ow[NR::X]) / sw[NR::X]) * sw[NR::X] + ow[NR::X];
gint const xlinestart = (gint) Inkscape::round((sxg - ow[NR::X]) / sw[NR::X]);
gdouble const syg = floor ((buf->rect.y0 - ow[NR::Y]) / sw[NR::Y]) * sw[NR::Y] + ow[NR::Y];
gint const ylinestart = (gint) Inkscape::round((syg - ow[NR::Y]) / sw[NR::Y]);
if (!render_dotted) {
gint ylinenum;
gdouble y;
for (y = syg, ylinenum = ylinestart; y < buf->rect.y1; y += sw[NR::Y], ylinenum++) {
gint const y0 = (gint) Inkscape::round(y);
if (!scaled[NR::Y] && (ylinenum % empspacing) == 0) {
grid_hline (buf, y0, buf->rect.x0, buf->rect.x1 - 1, empcolor);
} else {
grid_hline (buf, y0, buf->rect.x0, buf->rect.x1 - 1, color);
}
}
gint xlinenum;
gdouble x;
for (x = sxg, xlinenum = xlinestart; x < buf->rect.x1; x += sw[NR::X], xlinenum++) {
gint const ix = (gint) Inkscape::round(x);
if (!scaled[NR::X] && (xlinenum % empspacing) == 0) {
grid_vline (buf, ix, buf->rect.y0, buf->rect.y1, empcolor);
} else {
grid_vline (buf, ix, buf->rect.y0, buf->rect.y1, color);
}
}
} else {
gint ylinenum;
gdouble y;
for (y = syg, ylinenum = ylinestart; y < buf->rect.y1; y += sw[NR::Y], ylinenum++) {
gint const iy = (gint) Inkscape::round(y);
gint xlinenum;
gdouble x;
for (x = sxg, xlinenum = xlinestart; x < buf->rect.x1; x += sw[NR::X], xlinenum++) {
gint const ix = (gint) Inkscape::round(x);
if ( (!scaled[NR::X] && (xlinenum % empspacing) == 0)
|| (!scaled[NR::Y] && (ylinenum % empspacing) == 0) )
{
grid_dot (buf, ix, iy, empcolor | (guint32)0x000000FF); // put alpha to max value
} else {
grid_dot (buf, ix, iy, color | (guint32)0x000000FF); // put alpha to max value
}
}
}
}
}
/**
* \return x rounded to the nearest multiple of c1 plus c0.
*
* \note
* If c1==0 (and c0 is finite), then returns +/-inf. This makes grid spacing of zero
* mean "ignore the grid in this dimention". We're currently discussing "good" semantics
* for guide/grid snapping.
*/
/* FIXME: move this somewhere else, perhaps */
static double round_to_nearest_multiple_plus(double x, double const c1, double const c0)
{
return floor((x - c0) / c1 + .5) * c1 + c0;
}
CanvasXYGridSnapper::CanvasXYGridSnapper(CanvasXYGrid *grid, SPNamedView const *nv, NR::Coord const d) : LineSnapper(nv, d)
{
this->grid = grid;
}
LineSnapper::LineList
CanvasXYGridSnapper::_getSnapLines(NR::Point const &p) const
{
LineList s;
if ( grid == NULL ) {
return s;
}
for (unsigned int i = 0; i < 2; ++i) {
/* This is to make sure we snap to only visible grid lines */
double scaled_spacing = grid->sw[i]; // this is spacing of visible lines if screen pixels
// convert screen pixels to px
// FIXME: after we switch to snapping dist in screen pixels, this will be unnecessary
if (SP_ACTIVE_DESKTOP) {
scaled_spacing /= SP_ACTIVE_DESKTOP->current_zoom();
}
NR::Coord const rounded = round_to_nearest_multiple_plus(p[i],
scaled_spacing,
grid->origin[i]);
s.push_back(std::make_pair(NR::Dim2(i), rounded));
}
return s;
}
}; /* 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:encoding=utf-8:textwidth=99 :