2011-02-07 1 views
2

J'ai écrit le code suivant pour placer le curseur d'un Gtk::Window à partir d'un Cairo::Context. Lorsque j'exécute le programme et déplace le curseur dans la fenêtre, le curseur se transforme en une ligne horizontale noire en haut, suivie par une forme blanche indéfinissable en bas. Je m'attendais à ce que le curseur se transforme en un carré noir de 16 × 16. Pourquoi le curseur n'atteint-il pas la forme voulue?Gtk +: Comment définir le curseur d'une fenêtre à partir d'un contexte Cairo?

#include <gtkmm.h> 

const int size = 16, hotspot = 0; 

class Window : public Gtk::Window 
{ 
    public: 
    void change_cursor() 
    { 
     Glib::RefPtr<Gdk::Drawable> pixmap = Gdk::Pixmap::create(
      Glib::RefPtr<Gdk::Drawable>(), size, size, get_window()->get_depth()); 
     pixmap->set_colormap(get_window()->get_colormap()); 
     Cairo::RefPtr<Cairo::Context> context = pixmap->create_cairo_context(); 
     context->set_source_rgba(0, 0, 0, 0); 
     context->rectangle(0, 0, size, size); 
     context->fill(); 
     Glib::RefPtr<Gdk::Pixbuf> pixbuf 
      = Gdk::Pixbuf::create(pixmap, 0, 0, size, size); 
     Gdk::Cursor cursor(get_window()->get_display(), pixbuf, hotspot, hotspot); 
     window->set_cursor(cursor); 
    } 
}; 

int main(int argc, char* argv[]) 
{ 
    Gtk::Main app(argc, argv); 
    Window window; 
    window.show_all(); 
    window.change_cursor(); 
    Gtk::Main::run(window); 
    return 0; 
} 

Quand je dessine le Gdk::Pixmap à l'écran, il semble bien. Quand je dessine le Gdk::Pixbuf à l'écran, je reçois des ordures.

Répondre

2

je ne figure pas la cause du problème, mais une façon de travailler autour d'elle:

  1. Créer un Gdk::Pixbuf vide.
  2. Créez un Cairo::ImageSurface en utilisant les pixels de Gdk::Pixbuf comme tampon de données.
  3. Créez un Cairo::Context à partir du Cairo::ImageSurface.
  4. Effacez le Cairo::Context (ceci est important car les données de pixel de Gdk::Pixbuf ne semblent pas encore être initialisées).

Le code ressemble à ceci:

Glib::RefPtr<Gdk::Pixbuf> pixbuf 
    = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, 8, size, size); 
Cairo::RefPtr<Cairo::ImageSurface> surface 
    = Cairo::ImageSurface::create(
      pixbuf->get_pixels(), Cairo::FORMAT_ARGB32, 
      size, size, pixbuf->get_rowstride()); 
Cairo::RefPtr<Cairo::Context> context = Cairo::Context::create(surface); 
context->save(); 
context->set_operator(Cairo::OPERATOR_CLEAR); 
context->paint(); 
context->restore(); 

Quand je peins maintenant à ce contexte et placez le curseur de la Gdk::Pixbuf, je reçois presque ce que je veux: la forme est très bien, mais rouge et Bleu sont échangés. Cela peut être fixé comme indiqué dans Question 4291994 (How to write contents of a Cairo Image surface into a Gdk Pixbuf?):

void fix_buffer_after_cairo(Glib::RefPtr<Gdk::Pixbuf> pixbuf) 
    { 
    guint8* pixels = pixbuf->get_pixels(); 
    int height = pixbuf->get_height(); 
    int width = pixbuf->get_width(); 
    int rowstride = pixbuf->get_rowstride(); 

    guint8 tmp; 
    guint8* p; 
    guint8* end; 

    for (int j = height; j > 0; --j) 
    { 
     p = pixels; 
     end = p + 4 * width; 
     while (p < end) 
     { 
     tmp = p[0]; 
     if (G_BYTE_ORDER == G_LITTLE_ENDIAN) 
     { 
      p[0] = p[2]; p[2] = tmp; 
     } 
     else 
     { 
      p[0] = p[1]; p[1] = p[2]; p[2] = p[3]; p[3] = tmp; 
     } 
     p += 4; 
     } 
     pixels += rowstride; 
    } 
    } 
} 
Questions connexes