Code

Color preview in cursor
authorJasper van de Gronde <th.v.d.gronde@hccnet.nl>
Mon, 6 Sep 2010 09:16:22 +0000 (11:16 +0200)
committerJasper van de Gronde <th.v.d.gronde@hccnet.nl>
Mon, 6 Sep 2010 09:16:22 +0000 (11:16 +0200)
src/arc-context.cpp
src/desktop-style.cpp
src/event-context.cpp
src/event-context.h
src/pixmaps/cursor-ellipse.xpm
src/pixmaps/cursor-rect.xpm
src/pixmaps/cursor-star.xpm
src/rect-context.cpp
src/sp-cursor.cpp
src/sp-cursor.h
src/star-context.cpp

index 3c0d9ccdaaa98966f37be5a9b7d3d1e55ae2e1da..ddfb8f9234ce2edd468d0786edc35dbca38c7bfc 100644 (file)
@@ -107,6 +107,7 @@ static void sp_arc_context_init(SPArcContext *arc_context)
     event_context->tolerance = 0;
     event_context->within_tolerance = false;
     event_context->item_to_select = NULL;
+    event_context->tool_url = "/tools/shapes/arc";
 
     arc_context->item = NULL;
 
index 5866b14fbe054637abcf8bee8d7f646ace0cf8ae..5615a8ea96d1cca3b259d2999b0cff14ac2dbe62 100644 (file)
@@ -41,6 +41,7 @@
 #include "xml/repr.h"
 #include "libnrtype/font-style-to-pos.h"
 #include "sp-path.h"
+#include "event-context.h"
 
 #include "desktop-style.h"
 #include "svg/svg-icc-color.h"
@@ -195,6 +196,10 @@ sp_desktop_set_style(SPDesktop *desktop, SPCSSAttr *css, bool change, bool write
 
 // 3. If nobody has intercepted the signal, apply the style to the selection
     if (!intercepted) {
+        // If we have an event context, update its cursor (TODO: it could be neater to do this with the signal sent above, but what if the signal gets intercepted?)
+        if (desktop->event_context) {
+            sp_event_context_update_cursor(desktop->event_context);
+        }
 
         // Remove text attributes if not text...
         // Do this once in case a zillion objects are selected.
index 5d60379c84b43a625c5ab583cd29ca7483e4558c..56f8758449538da39ff5546d2f1a93c3d443450c 100644 (file)
@@ -44,6 +44,7 @@
 #include "desktop.h"
 #include "desktop-handles.h"
 #include "desktop-events.h"
+#include "desktop-style.h"
 #include "widgets/desktop-widget.h"
 #include "sp-namedview.h"
 #include "selection.h"
@@ -62,6 +63,7 @@
 #include "ui/tool/control-point.h"
 #include "shape-editor.h"
 #include "sp-guide.h"
+#include "color.h"
 
 static void sp_event_context_class_init(SPEventContextClass *klass);
 static void sp_event_context_init(SPEventContext *event_context);
@@ -141,6 +143,7 @@ static void sp_event_context_init(SPEventContext *event_context) {
     event_context->shape_editor = NULL;
     event_context->_delayed_snap_event = NULL;
     event_context->_dse_callback_in_process = false;
+    event_context->tool_url = NULL;
 }
 
 /**
@@ -183,17 +186,38 @@ void sp_event_context_update_cursor(SPEventContext *ec) {
     if (w->window) {
         /* fixme: */
         if (ec->cursor_shape) {
-            GdkBitmap *bitmap = NULL;
-            GdkBitmap *mask = NULL;
-            sp_cursor_bitmap_and_mask_from_xpm(&bitmap, &mask, ec->cursor_shape);
-            if ((bitmap != NULL) && (mask != NULL)) {
-                if (ec->cursor)
-                    gdk_cursor_unref(ec->cursor);
-                ec->cursor = gdk_cursor_new_from_pixmap(bitmap, mask,
-                        &w->style->black, &w->style->white, ec->hot_x,
-                        ec->hot_y);
-                g_object_unref(bitmap);
-                g_object_unref(mask);
+            GdkDisplay *display = gdk_display_get_default();
+            if (ec->tool_url && gdk_display_supports_cursor_alpha(display) && gdk_display_supports_cursor_color(display)) {
+                bool fillHasColor=false, strokeHasColor=false;
+                guint32 fillColor = sp_desktop_get_color_tool(ec->desktop, ec->tool_url, true, &fillHasColor);
+                guint32 strokeColor = sp_desktop_get_color_tool(ec->desktop, ec->tool_url, false, &strokeHasColor);
+                double fillOpacity = fillHasColor ? sp_desktop_get_opacity_tool(ec->desktop, ec->tool_url, true) : 0;
+                double strokeOpacity = strokeHasColor ? sp_desktop_get_opacity_tool(ec->desktop, ec->tool_url, false) : 0;
+                GdkPixbuf *pixbuf = sp_cursor_pixbuf_from_xpm(
+                    ec->cursor_shape,
+                    w->style->black, w->style->white,
+                    SP_RGBA32_U_COMPOSE(SP_RGBA32_R_U(fillColor),SP_RGBA32_G_U(fillColor),SP_RGBA32_B_U(fillColor),SP_COLOR_F_TO_U(fillOpacity)),
+                    SP_RGBA32_U_COMPOSE(SP_RGBA32_R_U(strokeColor),SP_RGBA32_G_U(strokeColor),SP_RGBA32_B_U(strokeColor),SP_COLOR_F_TO_U(strokeOpacity))
+                    );
+                if (pixbuf != NULL) {
+                    if (ec->cursor)
+                        gdk_cursor_unref(ec->cursor);
+                    ec->cursor = gdk_cursor_new_from_pixbuf(display, pixbuf, ec->hot_x, ec->hot_y);
+                    g_object_unref(pixbuf);
+                }
+            } else {
+                GdkBitmap *bitmap = NULL;
+                GdkBitmap *mask = NULL;
+                sp_cursor_bitmap_and_mask_from_xpm(&bitmap, &mask, ec->cursor_shape);
+                if ((bitmap != NULL) && (mask != NULL)) {
+                    if (ec->cursor)
+                        gdk_cursor_unref(ec->cursor);
+                    ec->cursor = gdk_cursor_new_from_pixmap(bitmap, mask,
+                            &w->style->black, &w->style->white, ec->hot_x,
+                            ec->hot_y);
+                    g_object_unref(bitmap);
+                    g_object_unref(mask);
+                }
             }
         }
         gdk_window_set_cursor(w->window, ec->cursor);
index 76c74e26c63978f60a1de36528dc3ab1fb4dbb69..fc22762fdbd1b94d8072519a7ef05f6d1d81f0e3 100644 (file)
@@ -128,6 +128,8 @@ struct SPEventContext : public GObject {
 
     DelayedSnapEvent *_delayed_snap_event;
     bool _dse_callback_in_process;
+
+    char const * tool_url; ///< the (preferences) url for the tool (if a subclass corresponding to a tool is used)
 };
 
 /**
index 7a230bd55d5caa03746b503bfb50aa4c6ed77ee9..b0f20d18cefca60972add862446bd2708bda5d2d 100644 (file)
@@ -1,8 +1,10 @@
 /* XPM */
 static char const *cursor_ellipse_xpm[] = {
-"32 32 3 1",
+"32 32 5 1",
 "      c None",
 ".     c #FFFFFF",
+"%     c Stroke",
+"*     c Fill",
 "+     c #000000",
 "   ...                          ",
 "   .+.                          ",
@@ -12,17 +14,17 @@ static char const *cursor_ellipse_xpm[] = {
 "....+....                       ",
 "   .+.                          ",
 "   .+.       .......            ",
-"   ...    ....+++++....         ",
-"         ..+++.....+++..        ",
-"        ..+...........+..       ",
-"       ..+.............+..      ",
-"       .+...............+.      ",
-"       .+...............+.      ",
-"       .+...............+.      ",
-"       ..+.............+..      ",
-"        ..+...........+..       ",
-"         ..+++.....+++..        ",
-"          ....+++++....         ",
+"   ...    ....%%%%%....         ",
+"         ..%%%*****%%%..        ",
+"        ..%***********%..       ",
+"       ..%*************%..      ",
+"       .%***************%.      ",
+"       .%***************%.      ",
+"       .%***************%.      ",
+"       ..%*************%..      ",
+"        ..%***********%..       ",
+"         ..%%%*****%%%..        ",
+"          ....%%%%%....         ",
 "             .......            ",
 "                                ",
 "                                ",
index 149624aa7585a969a5aaa558f63deaa31535e190..69007bc772fada5f0ecec8feae9f7d514c883ec8 100644 (file)
@@ -1,8 +1,10 @@
 /* XPM */
 static char const *cursor_rect_xpm[] = {
-"32 32 3 1",
+"32 32 5 1",
 "      c None",
 ".     c #FFFFFF",
+"%     c Stroke",
+"*     c Fill",
 "+     c #000000",
 "   ...                          ",
 "   .+.                          ",
@@ -12,17 +14,17 @@ static char const *cursor_rect_xpm[] = {
 "....+....                       ",
 "   .+.                          ",
 "   .+. .................        ",
-"   ... .+++++++++++++++.        ",
-"       .+.............+.        ",
-"       .+.............+.        ",
-"       .+.............+.        ",
-"       .+.............+.        ",
-"       .+.............+.        ",
-"       .+.............+.        ",
-"       .+.............+.        ",
-"       .+.............+.        ",
-"       .+.............+.        ",
-"       .+++++++++++++++.        ",
+"   ... .%%%%%%%%%%%%%%%.        ",
+"       .%*************%.        ",
+"       .%*************%.        ",
+"       .%*************%.        ",
+"       .%*************%.        ",
+"       .%*************%.        ",
+"       .%*************%.        ",
+"       .%*************%.        ",
+"       .%*************%.        ",
+"       .%*************%.        ",
+"       .%%%%%%%%%%%%%%%.        ",
 "       .................        ",
 "                                ",
 "                                ",
index 80d312ace319ece924c755eefcebd00c85926148..eedf448e40fa315fa85ccd94113285147d07ebc3 100644 (file)
@@ -1,8 +1,10 @@
 /* XPM */
 static char const *cursor_star_xpm[] = {
-"32 32 3 1",
+"32 32 5 1",
 "      c None",
 ".     c #FFFFFF",
+"%     c Stroke",
+"*     c Fill",
 "+     c #000000",
 "   ...                          ",
 "   .+.                          ",
@@ -10,21 +12,21 @@ static char const *cursor_star_xpm[] = {
 "....+....                       ",
 ".+++ +++.                       ",
 "....+....      ..               ",
-"   .+.        .++.              ",
-"   .+.        .++.              ",
-"   ...        .++.              ",
-"             .+..+.             ",
-"      ........+..+........      ",
-"       .++++++....++++++.       ",
-"        .++..........++.        ",
-"         ..++......++..         ",
-"           .+......+.           ",
-"           .+......+.           ",
-"          .+...++...+.          ",
-"          .+.++..++.+.          ",
-"         .+.+..  ..+.+.         ",
-"         .++.      .++.         ",
-"         .+.        .+.         ",
+"   .+.        .%%.              ",
+"   .+.        .%%.              ",
+"   ...        .%%.              ",
+"             .%**%*             ",
+"      ........%**%........      ",
+"       .%%%%%%****%%%%%%.       ",
+"        .%%**********%%.        ",
+"         ..%%******%%..         ",
+"           .%******%.           ",
+"           .%******%.           ",
+"          .%***%%***%.          ",
+"          .%*%%..%%*%.          ",
+"         .%*%..  ..%*%.         ",
+"         .%%.      .%%.         ",
+"         .%.        .%.         ",
 "         ..          ..         ",
 "                                ",
 "                                ",
index d60a6630bcd3991ca5dcc76fae583386cc258f74..81f615571c71940c5d2f2454cbcf8727c983b1c8 100644 (file)
@@ -110,6 +110,7 @@ static void sp_rect_context_init(SPRectContext *rect_context)
     event_context->tolerance = 0;
     event_context->within_tolerance = false;
     event_context->item_to_select = NULL;
+    event_context->tool_url = "/tools/shapes/rect";
 
     rect_context->item = NULL;
 
index 4bbba5f10875748550293add149c905de30b6e12..5ec80c9f644a19fb93c38e05345038f7bfd253bd 100644 (file)
@@ -16,6 +16,8 @@
 #include <cstring>
 #include <string>
 #include <ctype.h>
+#include <map>
+#include "color.h"
 #include "sp-cursor.h"
 
 void
@@ -32,7 +34,7 @@ sp_cursor_bitmap_and_mask_from_xpm(GdkBitmap **bitmap, GdkBitmap **mask, gchar c
     g_return_if_fail (colors >= 3);
 
     int transparent_color = ' ';
-    int black_color = '.';
+    std::string black_colors;
 
     char pixmap_buffer[(32 * 32)/8];
     char mask_buffer[(32 * 32)/8];
@@ -51,12 +53,16 @@ sp_cursor_bitmap_and_mask_from_xpm(GdkBitmap **bitmap, GdkBitmap **mask, gchar c
             p++;
         }
 
-       if (strcmp(p, "None") == 0) {
+        if (strcmp(p, "None") == 0) {
             transparent_color = ccode;
         }
 
+        if (strcmp(p, "Stroke") == 0) {
+            black_colors.push_back(ccode);
+        }
+
         if (strcmp(p, "#000000") == 0) {
-            black_color = ccode;
+            black_colors.push_back(ccode);
         }
     }
 
@@ -67,10 +73,10 @@ sp_cursor_bitmap_and_mask_from_xpm(GdkBitmap **bitmap, GdkBitmap **mask, gchar c
             char maskv = 0;
                        
             for (int pix = 0; pix < 8; pix++, x++){
-                if (xpm[4+y][x] != transparent_color) {
+                if (xpm[1+colors+y][x] != transparent_color) {
                     maskv |= 1 << pix;
 
-                    if (xpm[4+y][x] == black_color) {
+                    if (black_colors.find(xpm[1+colors+y][x]) != std::string::npos) {
                         value |= 1 << pix;
                     }
                 }
@@ -85,6 +91,73 @@ sp_cursor_bitmap_and_mask_from_xpm(GdkBitmap **bitmap, GdkBitmap **mask, gchar c
     *mask   = gdk_bitmap_create_from_data(NULL, mask_buffer, 32, 32);
 }
 
+static void free_cursor_data(guchar *pixels, gpointer data) {
+    delete [] reinterpret_cast<guint32*>(pixels);
+}
+
+struct RGBA {
+    guchar v[4];
+    RGBA() { v[0] = 0; v[1] = 0; v[2] = 0; v[3] = 0; }
+    RGBA(guchar r, guchar g, guchar b, guchar a) { v[0] = r; v[1] = g; v[2] = b; v[3] = a; }
+    operator guint32 const () const { return *reinterpret_cast<guint32 const *>(v); }
+};
+
+GdkPixbuf*
+sp_cursor_pixbuf_from_xpm(gchar const *const *xpm, GdkColor const& black, GdkColor const& white, guint32 fill, guint32 stroke)
+{
+    int height;
+    int width;
+    int colors;
+    int pix;
+    sscanf(xpm[0], "%d %d %d %d", &height, &width, &colors, &pix);
+
+    //g_return_if_fail (height == 32);
+    //g_return_if_fail (width == 32);
+    //g_return_if_fail (colors >= 3);
+
+    std::map<char,RGBA> colorMap;
+
+    for (int i = 0; i < colors; i++) {
+
+        char const *p = xpm[1 + i];
+        char const ccode = *p;
+
+        p++;
+        while (isspace(*p)) {
+            p++;
+        }
+        p++;
+        while (isspace(*p)) {
+            p++;
+        }
+
+        if (strcmp(p, "None") == 0) {
+            colorMap.insert(std::make_pair(ccode, RGBA()));
+        } else if (strcmp(p, "Fill") == 0) {
+            colorMap.insert(std::make_pair(ccode, RGBA(SP_RGBA32_R_U(fill),SP_RGBA32_G_U(fill),SP_RGBA32_B_U(fill),SP_RGBA32_A_U(fill))));
+        } else if (strcmp(p, "Stroke") == 0) {
+            colorMap.insert(std::make_pair(ccode, RGBA(SP_RGBA32_R_U(stroke),SP_RGBA32_G_U(stroke),SP_RGBA32_B_U(stroke),SP_RGBA32_A_U(stroke))));
+        } else if (strcmp(p, "#000000") == 0) {
+            colorMap.insert(std::make_pair(ccode, RGBA(black.red,black.green,black.blue,255)));
+        } else if (strcmp(p, "#FFFFFF") == 0) {
+            colorMap.insert(std::make_pair(ccode, RGBA(white.red,white.green,white.blue,255)));
+        } else {
+            colorMap.insert(std::make_pair(ccode, RGBA()));
+        }
+    }
+
+    guint32 *pixmap_buffer = new guint32[width * height];
+
+    for (int y = 0; y < height; y++) {
+        for (int x = 0; x < width; x++) {
+            std::map<char,RGBA>::const_iterator it = colorMap.find(xpm[1+colors+y][x]);
+            pixmap_buffer[y * width + x] = it==colorMap.end() ? 0u : it->second;
+        }
+    }
+
+    return gdk_pixbuf_new_from_data(reinterpret_cast<guchar*>(pixmap_buffer), GDK_COLORSPACE_RGB, TRUE, 8, width, height, width*sizeof(guint32), free_cursor_data, NULL);
+}
+
 GdkCursor *
 sp_cursor_new_from_xpm(gchar const *const *xpm, gint hot_x, gint hot_y)
 {
index 1c40bdc44d053ff1306d7d912e2bbed58ecd1a9d..4ab90d16906b5ecfe1f2abf1b9630dbc5a3857cf 100644 (file)
@@ -4,6 +4,7 @@
 #include <gdk/gdk.h>
 
 void sp_cursor_bitmap_and_mask_from_xpm(GdkBitmap **bitmap, GdkBitmap **mask, gchar const *const *xpm);
+GdkPixbuf* sp_cursor_pixbuf_from_xpm(gchar const *const *xpm, GdkColor const& black, GdkColor const& white, guint32 fill, guint32 stroke);
 GdkCursor *sp_cursor_new_from_xpm(gchar const *const *xpm, gint hot_x, gint hot_y);
 
 #endif
index 9a2a67a57df229203b4d145ac172795d5b56fadb..603865ce16d966490602102fbdef7f132f769cc1 100644 (file)
@@ -111,6 +111,7 @@ sp_star_context_init (SPStarContext * star_context)
     event_context->tolerance = 0;
     event_context->within_tolerance = false;
     event_context->item_to_select = NULL;
+    event_context->tool_url = "/tools/shapes/star";
 
     star_context->item = NULL;