summaryrefslogtreecommitdiffstats
path: root/src/display/canvas-grid.cpp
diff options
context:
space:
mode:
authorMenTaLguY <mental@rydia.net>2006-01-16 02:36:01 +0000
committermental <mental@users.sourceforge.net>2006-01-16 02:36:01 +0000
commit179fa413b047bede6e32109e2ce82437c5fb8d34 (patch)
treea5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/display/canvas-grid.cpp
downloadinkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz
inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/display/canvas-grid.cpp')
-rw-r--r--src/display/canvas-grid.cpp308
1 files changed, 308 insertions, 0 deletions
diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp
new file mode 100644
index 000000000..6618c2358
--- /dev/null
+++ b/src/display/canvas-grid.cpp
@@ -0,0 +1,308 @@
+#define SP_CANVAS_GRID_C
+
+/*
+ * SPCGrid
+ *
+ * Copyright (C) Lauris Kaplinski 2000
+ *
+ */
+
+
+#include "sp-canvas-util.h"
+#include "canvas-grid.h"
+#include "display-forward.h"
+#include <libnr/nr-pixops.h>
+
+enum {
+ ARG_0,
+ ARG_ORIGINX,
+ ARG_ORIGINY,
+ ARG_SPACINGX,
+ ARG_SPACINGY,
+ ARG_COLOR,
+ ARG_EMPCOLOR,
+ ARG_EMPSPACING
+};
+
+
+static void sp_cgrid_class_init (SPCGridClass *klass);
+static void sp_cgrid_init (SPCGrid *grid);
+static void sp_cgrid_destroy (GtkObject *object);
+static void sp_cgrid_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);
+
+static void sp_cgrid_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags);
+static void sp_cgrid_render (SPCanvasItem *item, SPCanvasBuf *buf);
+
+static SPCanvasItemClass * parent_class;
+
+GtkType
+sp_cgrid_get_type (void)
+{
+ static GtkType cgrid_type = 0;
+
+ if (!cgrid_type) {
+ GtkTypeInfo cgrid_info = {
+ "SPCGrid",
+ sizeof (SPCGrid),
+ sizeof (SPCGridClass),
+ (GtkClassInitFunc) sp_cgrid_class_init,
+ (GtkObjectInitFunc) sp_cgrid_init,
+ NULL, NULL,
+ (GtkClassInitFunc) NULL
+ };
+ cgrid_type = gtk_type_unique (sp_canvas_item_get_type (), &cgrid_info);
+ }
+ return cgrid_type;
+}
+
+static void
+sp_cgrid_class_init (SPCGridClass *klass)
+{
+ GtkObjectClass *object_class;
+ SPCanvasItemClass *item_class;
+
+ object_class = (GtkObjectClass *) klass;
+ item_class = (SPCanvasItemClass *) klass;
+
+ parent_class = (SPCanvasItemClass*)gtk_type_class (sp_canvas_item_get_type ());
+
+ gtk_object_add_arg_type ("SPCGrid::originx", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ORIGINX);
+ gtk_object_add_arg_type ("SPCGrid::originy", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_ORIGINY);
+ gtk_object_add_arg_type ("SPCGrid::spacingx", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_SPACINGX);
+ gtk_object_add_arg_type ("SPCGrid::spacingy", GTK_TYPE_DOUBLE, GTK_ARG_WRITABLE, ARG_SPACINGY);
+ gtk_object_add_arg_type ("SPCGrid::color", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_COLOR);
+ gtk_object_add_arg_type ("SPCGrid::empcolor", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_EMPCOLOR);
+ gtk_object_add_arg_type ("SPCGrid::empspacing", GTK_TYPE_INT, GTK_ARG_WRITABLE, ARG_EMPSPACING);
+
+ object_class->destroy = sp_cgrid_destroy;
+ object_class->set_arg = sp_cgrid_set_arg;
+
+ item_class->update = sp_cgrid_update;
+ item_class->render = sp_cgrid_render;
+}
+
+static void
+sp_cgrid_init (SPCGrid *grid)
+{
+ grid->origin[NR::X] = grid->origin[NR::Y] = 0.0;
+ grid->spacing[NR::X] = grid->spacing[NR::Y] = 8.0;
+ grid->color = 0x0000ff7f;
+ grid->empcolor = 0x3F3FFF40;
+ grid->empspacing = 5;
+}
+
+static void
+sp_cgrid_destroy (GtkObject *object)
+{
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (SP_IS_CGRID (object));
+
+ if (GTK_OBJECT_CLASS (parent_class)->destroy)
+ (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+static void
+sp_cgrid_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
+{
+ SPCanvasItem *item = SP_CANVAS_ITEM (object);
+ SPCGrid *grid = SP_CGRID (object);
+
+ switch (arg_id) {
+ case ARG_ORIGINX:
+ grid->origin[NR::X] = GTK_VALUE_DOUBLE (* arg);
+ sp_canvas_item_request_update (item);
+ break;
+ case ARG_ORIGINY:
+ grid->origin[NR::Y] = GTK_VALUE_DOUBLE (* arg);
+ sp_canvas_item_request_update (item);
+ break;
+ case ARG_SPACINGX:
+ grid->spacing[NR::X] = GTK_VALUE_DOUBLE (* arg);
+ if (grid->spacing[NR::X] < 0.01) grid->spacing[NR::X] = 0.01;
+ sp_canvas_item_request_update (item);
+ break;
+ case ARG_SPACINGY:
+ grid->spacing[NR::Y] = GTK_VALUE_DOUBLE (* arg);
+ if (grid->spacing[NR::Y] < 0.01) grid->spacing[NR::Y] = 0.01;
+ sp_canvas_item_request_update (item);
+ break;
+ case ARG_COLOR:
+ grid->color = GTK_VALUE_INT (* arg);
+ sp_canvas_item_request_update (item);
+ break;
+ case ARG_EMPCOLOR:
+ grid->empcolor = GTK_VALUE_INT (* arg);
+ sp_canvas_item_request_update (item);
+ break;
+ case ARG_EMPSPACING:
+ grid->empspacing = GTK_VALUE_INT (* arg);
+ // std::cout << "Emphasis Spacing: " << grid->empspacing << std::endl;
+ sp_canvas_item_request_update (item);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+sp_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 (r, a, p[0]);
+ p[1] = NR_COMPOSEN11 (g, a, p[1]);
+ p[2] = NR_COMPOSEN11 (b, a, p[2]);
+ p += 3;
+ }
+ }
+}
+
+static void
+sp_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 (r, a, p[0]);
+ p[1] = NR_COMPOSEN11 (g, a, p[1]);
+ p[2] = NR_COMPOSEN11 (b, a, p[2]);
+ p += buf->buf_rowstride;
+ }
+ }
+}
+
+/**
+ \brief This function renders the grid on a particular canvas buffer
+ \param item The grid to render on the buffer
+ \param buf The buffer to render the grid on
+
+ This function gets called a touch more than you might believe,
+ about once per tile. This means that it could probably be optimized
+ and help things out.
+
+ Basically this function has to determine where in the canvas it is,
+ and how that associates with the grid. It does this first by looking
+ at the bounding box of the buffer, and then calculates where the grid
+ starts in that buffer. It will then step through grid lines until
+ it is outside of the buffer.
+
+ For each grid line it is drawn using the function \c sp_grid_hline
+ or \c sp_grid_vline. These are convience functions for the sake
+ of making the function easier to read.
+
+ Also, there are emphisized lines on the grid. While the \c syg and
+ \c sxg variable track grid positioning, the \c xlinestart and \c
+ ylinestart variables track the 'count' of what lines they are. If
+ that count is a multiple of the line seperation between emphisis
+ lines, then that line is drawn in the emphisis color.
+*/
+static void
+sp_cgrid_render (SPCanvasItem * item, SPCanvasBuf * buf)
+{
+ SPCGrid *grid = SP_CGRID (item);
+
+ sp_canvas_prepare_buffer (buf);
+
+ const gdouble sxg = floor ((buf->rect.x0 - grid->ow[NR::X]) / grid->sw[NR::X]) * grid->sw[NR::X] + grid->ow[NR::X];
+ const gint xlinestart = (gint) Inkscape::round((sxg - grid->ow[NR::X]) / grid->sw[NR::X]);
+ const gdouble syg = floor ((buf->rect.y0 - grid->ow[NR::Y]) / grid->sw[NR::Y]) * grid->sw[NR::Y] + grid->ow[NR::Y];
+ const gint ylinestart = (gint) Inkscape::round((syg - grid->ow[NR::Y]) / grid->sw[NR::Y]);
+
+ gint ylinenum;
+ gdouble y;
+ for (y = syg, ylinenum = ylinestart; y < buf->rect.y1; y += grid->sw[NR::Y], ylinenum++) {
+ const gint y0 = (gint) Inkscape::round(y);
+ const gint y1 = (gint) Inkscape::round(y + grid->sw[NR::Y]);
+
+ if (!grid->scaled[NR::Y] &&
+ (ylinenum % grid->empspacing) == 0) {
+ sp_grid_hline (buf, y0, buf->rect.x0, buf->rect.x1 - 1, grid->empcolor);
+ } else {
+ sp_grid_hline (buf, y0, buf->rect.x0, buf->rect.x1 - 1, grid->color);
+ }
+
+ gint xlinenum;
+ gdouble x;
+ for (x = sxg, xlinenum = xlinestart; x < buf->rect.x1; x += grid->sw[NR::X], xlinenum++) {
+ const gint ix = (gint) Inkscape::round(x);
+ if (!grid->scaled[NR::X] &&
+ (xlinenum % grid->empspacing) == 0) {
+ sp_grid_vline (buf, ix, y0 + 1, y1 - 1, grid->empcolor);
+ } else {
+ sp_grid_vline (buf, ix, y0 + 1, y1 - 1, grid->color);
+ }
+ }
+ }
+}
+
+static void
+sp_cgrid_update (SPCanvasItem *item, NR::Matrix const &affine, unsigned int flags)
+{
+ SPCGrid *grid = SP_CGRID (item);
+
+ if (parent_class->update)
+ (* parent_class->update) (item, affine, flags);
+
+ grid->ow = grid->origin * affine;
+ grid->sw = grid->spacing * affine;
+ grid->sw -= NR::Point(affine[4], affine[5]);
+
+ for(int dim = 0; dim < 2; dim++) {
+ gint scaling_factor = grid->empspacing;
+
+ if (scaling_factor <= 1)
+ scaling_factor = 5;
+
+ grid->scaled[dim] = FALSE;
+ grid->sw[dim] = fabs (grid->sw[dim]);
+ while (grid->sw[dim] < 8.0) {
+ grid->scaled[dim] = TRUE;
+ grid->sw[dim] *= scaling_factor;
+ /* First pass, go up to the major line spacing, then
+ keep increasing by two. */
+ scaling_factor = 2;
+ }
+ }
+
+ if (grid->empspacing == 0) {
+ grid->scaled[NR::Y] = TRUE;
+ grid->scaled[NR::X] = TRUE;
+ }
+
+ sp_canvas_request_redraw (item->canvas,
+ -1000000, -1000000,
+ 1000000, 1000000);
+
+ item->x1 = item->y1 = -1000000;
+ item->x2 = item->y2 = 1000000;
+}
+
+/*
+ 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 :