Re: cairo drawing commands to gdk_invalidate_region



Sorry, I still don't get it. In my scenario there is initially is no external request of a region that should be drawn. The only source of what should be drawn, including what areas should be exposed, are in the draw() routine. The challenge is to translate a set of drawing routines to a set of invalidation areas.

In any case I solved it as follows:
I hope to post the entire code on github in the next few days.

    // Call drawing_cb to and use it to generate the rectangle list
    DovtkLassoRectangleList *rect_list = NULL;
    int scale_factor = 32;
    int low_res_width = (selfp->widget->allocation.width+scale_factor-1) / scale_factor;
    int low_res_height = (selfp->widget->allocation.height+scale_factor-1) / scale_factor;

    int i;

    // This should be created in the creation of DovtkLasso
    cairo_t *cr = NULL;
    cairo_surface_t *surf = NULL;

    if (selfp->do_calc_expose_from_cairo) {
        surf=cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
                                        low_res_width,
                                        low_res_height);
        cr = cairo_create(surf);
        cairo_set_source_rgba(cr,0,0,0,0);
        cairo_rectangle(cr, 0,0,low_res_height,low_res_width);
        cairo_fill(cr);
        cairo_set_source_rgba(cr,0,0,0,1);
    }
    cairo_scale(cr,1.0/scale_factor,1.0/scale_factor);
    selfp->drawing_cb(cr, TRUE, &rect_list);


    // Turn surf into a list of rectangles
    if (selfp->do_calc_expose_from_cairo) {
        int row_idx, col_idx;

        // Allocate worse case space
        rect_list = dovtk_lasso_rectangle_list_new(low_res_width*low_res_height);

        guint8 *buf = cairo_image_surface_get_data(surf);
        int rect_idx = 0;
        int row_stride = cairo_image_surface_get_stride(surf);
        for (row_idx=0; row_idx<low_res_height; row_idx++) {
            for (col_idx=0; col_idx<low_res_width; col_idx++) {
// Check for "dirty" pixel and turn it into a tile
                if (*(buf + row_stride * row_idx + col_idx * 4+3) > 0) {
                    cairo_rectangle_t *rect = &rect_list->rectangles[rect_idx++];
                    rect->x = col_idx*scale_factor;
                    rect->y = row_idx*scale_factor;
                    rect->width = scale_factor;
                    rect->height = scale_factor;
                }
            }
        }
        rect_list->num_rectangles = rect_idx;

        cairo_destroy(cr);
        cairo_surface_destroy(surf);
    }
    //    printf("num_rectangles = %d\n", rect_list->num_rectangles);

    // Build a list of expose rectangles from the old and the new lists.
    // Better done as a linked list.
    DovtkLassoRectangleList *expose_rect_list
        = dovtk_lasso_rectangle_list_new(selfp->old_rect_list->num_rectangles
                                         + rect_list->num_rectangles);
    int num_old_rects = selfp->old_rect_list->num_rectangles;
    for (i=0; i<num_old_rects; i++)
        expose_rect_list->rectangles[i] = selfp->old_rect_list->rectangles[i];
    for (i=0; i<rect_list->num_rectangles; i++)
        expose_rect_list->rectangles[num_old_rects + i] = rect_list->rectangles[i];

    // Expose the old and the new list of rectangles!
    for (i=0; i<expose_rect_list->num_rectangles; i++) {
        // Shortcut
        cairo_rectangle_t *lasso_rect = &expose_rect_list->rectangles[i];

        GdkRectangle rect;
        rect.x = lasso_rect->x;
        rect.y = lasso_rect->y;
        rect.width = lasso_rect->width;
        rect.height = lasso_rect->height;
#if 0
        printf("Invalidate region (%d,%d,%d,%d).\n",
               rect.x,rect.y,rect.width,rect.height);
#endif
        gdk_window_invalidate_rect(selfp->widget->window,
                                   &rect,
                                   TRUE);
    }


On Tue, Aug 17, 2010 at 15:42, Paul Davis <paul linuxaudiosystems com> wrote:
On Tue, Aug 17, 2010 at 4:39 AM, Dov Grobgeld <dov grobgeld gmail com> wrote:
> Thanks, but this is not what I am looking for.
>
> Here is a description of my flow, which might e.g. be used to draw a rubber
> band box:


based on an IRC exchange about this a couple of days ago, the answer
is two-fold:

1) you assume that cairo_clip() was called with ev->region before
draw() is invokved
2) you call something like cairo_clip_rectangle_lists() to get the
list of rects that need to be redrawn

there have been some suggestions that one should ignore this and just
redraw everything and let cairo clipping deal with it, but i think
this is clearly wrong when the drawing is computationally expensive.

--p



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]