Changeset 711

Show
Ignore:
Timestamp:
06/07/09 16:19:06 (4 years ago)
Author:
bjourne
Message:

Implemented more stuff of the GtkImageToolCairo system.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • gtkimageview/src/gtkiimagecairoshaper.c

    r709 r711  
    5252                               int                   y) 
    5353{ 
    54     return GTK_IIMAGE_CAIRO_SHAPER_GET_CLASS (shaper)->start (shaper, x, y); 
     54    GTK_IIMAGE_CAIRO_SHAPER_GET_CLASS (shaper)->start (shaper, x, y); 
     55
     56 
     57void 
     58gtk_iimage_cairo_shaper_motion (GtkIImageCairoShaper *shaper, 
     59                                int                   x, 
     60                                int                   y) 
     61
     62    GTK_IIMAGE_CAIRO_SHAPER_GET_CLASS (shaper)->motion (shaper, x, y); 
    5563} 
    5664 
     
    5866gtk_iimage_cairo_shaper_reset (GtkIImageCairoShaper *shaper) 
    5967{ 
    60     return GTK_IIMAGE_CAIRO_SHAPER_GET_CLASS (shaper)->reset (shaper); 
     68    GTK_IIMAGE_CAIRO_SHAPER_GET_CLASS (shaper)->reset (shaper); 
    6169} 
    6270 
     71void 
     72gtk_iimage_cairo_shaper_get_damage_area (GtkIImageCairoShaper *shaper, 
     73                                         GdkRectangle         *damage_area) 
     74{ 
     75    GTK_IIMAGE_CAIRO_SHAPER_GET_CLASS (shaper)-> 
     76        get_damage_area (shaper, damage_area); 
     77} 
     78 
     79void           
     80gtk_iimage_cairo_shaper_draw (GtkIImageCairoShaper *shaper, 
     81                              cairo_t              *cr) 
     82{ 
     83    GTK_IIMAGE_CAIRO_SHAPER_GET_CLASS (shaper)->draw (shaper, cr); 
     84} 
     85 
     86 
  • gtkimageview/src/gtkiimagecairoshaper.h

    r709 r711  
    4040                                              int                   x, 
    4141                                              int                   y); 
     42    void           (*motion)                 (GtkIImageCairoShaper *shaper, 
     43                                              int                   x, 
     44                                              int                   y); 
    4245    void           (*reset)                  (GtkIImageCairoShaper *shaper); 
     46    void           (*get_damage_area)        (GtkIImageCairoShaper *shaper, 
     47                                              GdkRectangle         *damage_area); 
     48    void           (*draw)                   (GtkIImageCairoShaper *shaper, 
     49                                              cairo_t              *cr); 
    4350}; 
    4451 
     
    4855                                                 int                   x, 
    4956                                                 int                   y); 
     57void          gtk_iimage_cairo_shaper_motion    (GtkIImageCairoShaper *shaper, 
     58                                                 int                   x, 
     59                                                 int                   y); 
    5060void          gtk_iimage_cairo_shaper_reset     (GtkIImageCairoShaper *shaper); 
     61void          gtk_iimage_cairo_shaper_get_damage_area (GtkIImageCairoShaper *shaper, 
     62                                                       GdkRectangle         *damage_area);  
     63void          gtk_iimage_cairo_shaper_draw      (GtkIImageCairoShaper *shaper, 
     64                                                 cairo_t              *cr); 
    5165 
    5266G_END_DECLS 
  • gtkimageview/src/gtkimagetoolcairo.c

    r709 r711  
    2121 
    2222/*************************************************************/ 
     23/***** Copy functions ****************************************/ 
     24/*************************************************************/ 
     25/** 
     26 * gdk_pixbuf_copy_to_surface: 
     27 * 
     28 * Copies a rectanguar area in a pixbuf to a cairo surface. This 
     29 * function should be as fast as possible which I don't know if it is. 
     30 **/ 
     31static void 
     32gdk_pixbuf_copy_to_surface (GdkPixbuf       *pixbuf, 
     33                            GdkRectangle    *rect, 
     34                            cairo_surface_t *surface) 
     35{ 
     36    cairo_t *cr = cairo_create (surface); 
     37    gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0); 
     38    cairo_rectangle (cr, rect->x, rect->y, rect->width, rect->height); 
     39    cairo_clip (cr); 
     40    cairo_paint (cr); 
     41    cairo_destroy (cr); 
     42} 
     43 
     44/** 
     45 * cairo_image_surface_copy: 
     46 * 
     47 * Copies a rectangular area in a cairo surface on another surface. 
     48 **/ 
     49static void 
     50cairo_image_surface_copy (cairo_surface_t *src, 
     51                          GdkRectangle    *rect, 
     52                          cairo_surface_t *dst) 
     53{ 
     54    cairo_pattern_t *pattern = cairo_pattern_create_for_surface (src); 
     55    cairo_t *cr = cairo_create (dst); 
     56    cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE); 
     57    cairo_rectangle (cr, rect->x, rect->y, rect->width, rect->height); 
     58    cairo_clip (cr); 
     59    cairo_set_source (cr, pattern); 
     60    cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); 
     61    cairo_paint (cr); 
     62    cairo_destroy (cr); 
     63    cairo_pattern_destroy (pattern); 
     64} 
     65 
     66 
     67/*************************************************************/ 
    2368/***** Static stuff ******************************************/ 
    2469/*************************************************************/ 
     70/** 
     71 * gtk_image_tool_cairo_set_redraw_area: 
     72 * 
     73 * Clips the input rectangle against the pixbuf size and sets it as 
     74 * the new redraw area. 
     75 **/ 
     76static void 
     77gtk_image_tool_cairo_set_redraw_area (GtkImageToolCairo *cairo, 
     78                                      GdkRectangle      *rect) 
     79{ 
     80    GdkPixbuf *pixbuf = cairo->pixbuf; 
     81    GdkRectangle pb_rect = {0, 0,  
     82                            gdk_pixbuf_get_width (pixbuf),  
     83                            gdk_pixbuf_get_height (pixbuf)}; 
     84    gdk_rectangle_intersect (&pb_rect, rect, rect); 
     85    cairo->redraw_area = *rect; 
     86} 
     87 
     88/** 
     89 * gtk_image_tool_cairo_surface_changed: 
     90 * 
     91 * Invalidate the cache and force a redraw of the damaged area. I'm 
     92 * not sure whether the queued redraw area should be padded or not. 
     93 **/ 
     94static void 
     95gtk_image_tool_cairo_surface_changed (GtkImageToolCairo *cairo, 
     96                                      GdkRectangle      *rect) 
     97{ 
     98    gdk_pixbuf_draw_cache_invalidate (cairo->cache); 
     99    GdkRectangle wid_rect; 
     100    gtk_image_view_image_to_widget_rect (cairo->view, rect, &wid_rect); 
     101    gtk_widget_queue_draw_area (GTK_WIDGET (cairo->view), 
     102                                wid_rect.x, wid_rect.y, 
     103                                wid_rect.width, wid_rect.height); 
     104} 
     105 
     106/** 
     107 * gtk_image_tool_cairo_null_surfaces: 
     108 * 
     109 * Ensure that the cairo surfaces are destroyed and set to %NULL. 
     110 **/ 
     111static void 
     112gtk_image_tool_cairo_null_surfaces (GtkImageToolCairo *cairo) 
     113{ 
     114    if (!cairo->image_surface) 
     115        return; 
     116    cairo_surface_destroy (cairo->image_surface); 
     117    cairo_surface_destroy (cairo->draw_surface); 
     118    cairo->image_surface = NULL; 
     119    cairo->draw_surface = NULL; 
     120} 
    25121 
    26122/*************************************************************/ 
     
    37133 
    38134static gboolean 
    39 button_press (GtkIImageTool  *tool, 
    40               GdkEventButton *ev) 
    41 
    42     GtkImageToolCairo *cairo = GTK_IMAGE_TOOL_CAIRO (tool); 
     135motion_notify (GtkIImageTool  *tool, 
     136               GdkEventMotion *ev) 
     137
     138    GtkImageToolCairo *cairo = GTK_IMAGE_TOOL_CAIRO (tool); 
     139    mouse_handler_motion_notify (cairo->mouse_handler, ev); 
     140    if (!cairo->mouse_handler->dragging) 
     141        return FALSE; 
     142 
    43143    GdkRectangle widget_rect = {ev->x, ev->y, 0, 0}; 
    44144    GdkRectangle image_rect; 
     
    47147                                              &image_rect)) 
    48148        return FALSE; 
     149     
     150    GdkRectangle old_damage_area, new_damage_area; 
     151    gtk_iimage_cairo_shaper_get_damage_area (cairo->shaper, &old_damage_area); 
     152    gtk_iimage_cairo_shaper_motion (cairo->shaper, image_rect.x, image_rect.y); 
     153    gtk_iimage_cairo_shaper_get_damage_area (cairo->shaper, &new_damage_area); 
     154 
     155    // Union the areas to get the complete redraw area. 
     156    if (cairo->redraw_area.x == -1) 
     157        cairo->redraw_area = old_damage_area; 
     158 
     159    GdkRectangle total_damage_area; 
     160    gdk_rectangle_union (&cairo->redraw_area, 
     161                         &new_damage_area, 
     162                         &total_damage_area); 
     163    gtk_image_tool_cairo_set_redraw_area (cairo, &total_damage_area); 
     164    gtk_image_tool_cairo_surface_changed (cairo, &cairo->redraw_area); 
     165    return TRUE; 
     166} 
     167 
     168static gboolean 
     169button_press (GtkIImageTool  *tool, 
     170              GdkEventButton *ev) 
     171{ 
     172    GtkImageToolCairo *cairo = GTK_IMAGE_TOOL_CAIRO (tool); 
     173    GdkRectangle widget_rect = {ev->x, ev->y, 0, 0}; 
     174    GdkRectangle image_rect; 
     175    if (!gtk_image_view_widget_to_image_rect (cairo->view, 
     176                                              &widget_rect, 
     177                                              &image_rect)) 
     178        return FALSE; 
    49179 
    50180    if (!mouse_handler_button_press (cairo->mouse_handler, ev)) 
     
    60190{ 
    61191    GtkImageToolCairo *cairo = GTK_IMAGE_TOOL_CAIRO (tool); 
     192 
     193    GdkRectangle damage_area; 
     194    gtk_iimage_cairo_shaper_get_damage_area (cairo->shaper, &damage_area); 
     195    gtk_image_tool_cairo_set_redraw_area (cairo, &damage_area); 
     196 
     197    // Let the shaper draw on the image surface. 
     198    cairo_t *cr = cairo_create (cairo->image_surface); 
     199    cairo_rectangle (cr, 
     200                     cairo->redraw_area.x, cairo->redraw_area.y, 
     201                     cairo->redraw_area.width, cairo->redraw_area.height); 
     202    cairo_clip (cr); 
     203    gtk_iimage_cairo_shaper_draw (cairo->shaper, cr); 
     204    cairo_destroy (cr); 
     205     
    62206    gtk_iimage_cairo_shaper_reset (cairo->shaper); 
     207    // These two calls means we will do a double-draw but it cannot be 
     208    // helped. 
     209    gtk_image_tool_cairo_surface_changed (cairo, &cairo->redraw_area); 
     210    gtk_image_view_damage_pixels (cairo->view, &cairo->redraw_area); 
    63211    return mouse_handler_button_release (cairo->mouse_handler, ev); 
    64 } 
    65  
    66 static gboolean 
    67 motion_notify (GtkIImageTool  *tool, 
    68                GdkEventMotion *ev) 
    69 { 
    70     //GtkImageToolCairo *cairo = GTK_IMAGE_TOOL_CAIRO (tool); 
    71     return TRUE; 
    72212} 
    73213 
     
    87227{ 
    88228    GtkImageToolCairo *cairo = GTK_IMAGE_TOOL_CAIRO (tool); 
    89     gdk_pixbuf_draw_cache_invalidate (cairo->cache); 
     229    GdkPixbuf *pixbuf = gtk_image_view_get_pixbuf (cairo->view); 
     230    if (!pixbuf) 
     231    { 
     232        gtk_image_tool_cairo_null_surfaces (cairo); 
     233        return; 
     234    } 
     235 
     236    // The pixbuf instance is the same but data in it has changed, we 
     237    // can ignore that. 
     238    if (pixbuf == cairo->pixbuf && cairo->overwritable_pixbuf) 
     239        return; 
     240 
     241    cairo->pixbuf = pixbuf; 
     242 
     243    int width = gdk_pixbuf_get_width (pixbuf); 
     244    int height = gdk_pixbuf_get_height (pixbuf); 
     245    cairo_format_t format = CAIRO_FORMAT_RGB24; 
     246    if (gdk_pixbuf_get_has_alpha (pixbuf)) 
     247        format = CAIRO_FORMAT_ARGB32; 
     248     
     249    if (!cairo->image_surface 
     250        || cairo_image_surface_get_width (cairo->image_surface) != width 
     251        || cairo_image_surface_get_height (cairo->image_surface) != height 
     252        || cairo_image_surface_get_format (cairo->image_surface) != format) 
     253    { 
     254        gtk_image_tool_cairo_null_surfaces (cairo); 
     255        cairo->image_surface = cairo_image_surface_create (format, 
     256                                                           width, height); 
     257        cairo->draw_surface = cairo_image_surface_create (format, 
     258                                                          width, height); 
     259    } 
     260 
     261    // The damaged area. 
     262    GdkRectangle damage = {0, 0, width, height}; 
     263    if (rect) 
     264        damage = *rect; 
     265 
     266    // Copy contents to cairo surfaces and schedule a redraw. 
     267    gdk_pixbuf_copy_to_surface (pixbuf, &damage, cairo->image_surface); 
     268    cairo_image_surface_copy (cairo->image_surface, 
     269                              &damage, 
     270                              cairo->draw_surface); 
     271    gtk_image_tool_cairo_surface_changed (cairo, &damage); 
    90272} 
    91273 
     
    120302    gdk_pixbuf_draw_cache_free (cairo->cache); 
    121303    g_free (cairo->mouse_handler); 
     304    gtk_image_tool_cairo_null_surfaces (cairo); 
    122305 
    123306    /* Chain up */ 
     
    189372    cairo->cache = gdk_pixbuf_draw_cache_new (); 
    190373    cairo->mouse_handler = mouse_handler_new (cairo->crosshair); 
     374    cairo->redraw_area = (GdkRectangle){-1, -1, -1, -1}; 
    191375} 
    192376