Logo Search packages:      
Sourcecode: inkscape version File versions

static int sp_canvas_paint_rect_internal ( PaintRectSetup const *  setup,
NRRectL  this_rect 
) [static]

Paint the given rect, recursively subdividing the region until it is the size of a single buffer.

Returns:
true if the drawing completes

Definition at line 1749 of file sp-canvas.cpp.

References sp_canvas_paint_single_buffer().

Referenced by sp_canvas_paint_rect(), and sp_canvas_paint_rect_internal().

{
    GTimeVal now;
    g_get_current_time (&now);

    glong elapsed = (now.tv_sec - setup->start_time.tv_sec) * 1000000
        + (now.tv_usec - setup->start_time.tv_usec);

    // Allow only very fast buffers to be run together;
    // as soon as the total redraw time exceeds 1ms, cancel;
    // this returns control to the idle loop and allows Inkscape to process user input
    // (potentially interrupting the redraw); as soon as Inkscape has some more idle time,
    // it will get back and finish painting what remains to paint.
    if (elapsed > 1000) {

        // Interrupting redraw isn't always good.
        // For example, when you drag one node of a big path, only the buffer containing
        // the mouse cursor will be redrawn again and again, and the rest of the path
        // will remain stale because Inkscape never has enough idle time to redraw all
        // of the screen. To work around this, such operations set a forced_redraw_limit > 0.
        // If this limit is set, and if we have aborted redraw more times than is allowed,
        // interrupting is blocked and we're forced to redraw full screen once
        // (after which we can again interrupt forced_redraw_limit times).
        if (setup->canvas->forced_redraw_limit < 0 ||
            setup->canvas->forced_redraw_count < setup->canvas->forced_redraw_limit) {

            if (setup->canvas->forced_redraw_limit != -1) {
                setup->canvas->forced_redraw_count++;
            }

            return false;
        }
    }

    // Find the optimal buffer dimensions
    int bw = this_rect.x1 - this_rect.x0;
    int bh = this_rect.y1 - this_rect.y0;
    if ((bw < 1) || (bh < 1))
        return 0;

    if (bw * bh < setup->max_pixels) {
        // We are small enough
        sp_canvas_paint_single_buffer (setup->canvas,
                                       this_rect.x0, this_rect.y0,
                                       this_rect.x1, this_rect.y1,
                                       setup->big_rect.x0, setup->big_rect.y0,
                                       setup->big_rect.x1, setup->big_rect.y1, bw);
        return 1;
    }

    NRRectL lo = this_rect;
    NRRectL hi = this_rect;

/*
This test determines the redraw strategy:

bw < bh (strips mode) splits across the smaller dimension of the rect and therefore (on
horizontally-stretched windows) results in redrawing in horizontal strips (from cursor point, in
both directions if the cursor is in the middle). This is traditional for Inkscape since old days,
and seems to be faster for drawings with many smaller objects at zoom-out.

bw > bh (chunks mode) splits across the larger dimension of the rect and therefore paints in
almost-square chunks, again from the cursor point. It's sometimes faster for drawings with few slow
(e.g. blurred) objects crossing the entire screen. It also appears to be somewhat psychologically
faster.

The default for now is the strips mode.
*/
    if (bw < bh || bh < 2 * TILE_SIZE) {
        // to correctly calculate the mean of two ints, we need to sum them into a larger int type
        int mid = ((long long) this_rect.x0 + (long long) this_rect.x1) / 2;
        // Make sure that mid lies on a tile boundary
        mid = (mid / TILE_SIZE) * TILE_SIZE;

        lo.x1 = mid;
        hi.x0 = mid;

        if (setup->mouse_loc[Geom::X] < mid) {
            // Always paint towards the mouse first
            return sp_canvas_paint_rect_internal(setup, lo)
                && sp_canvas_paint_rect_internal(setup, hi);
        } else {
            return sp_canvas_paint_rect_internal(setup, hi)
                && sp_canvas_paint_rect_internal(setup, lo);
        }
    } else {
        // to correctly calculate the mean of two ints, we need to sum them into a larger int type
        int mid = ((long long) this_rect.y0 + (long long) this_rect.y1) / 2;
        // Make sure that mid lies on a tile boundary
        mid = (mid / TILE_SIZE) * TILE_SIZE;

        lo.y1 = mid;
        hi.y0 = mid;

        if (setup->mouse_loc[Geom::Y] < mid) {
            // Always paint towards the mouse first
            return sp_canvas_paint_rect_internal(setup, lo)
                && sp_canvas_paint_rect_internal(setup, hi);
        } else {
            return sp_canvas_paint_rect_internal(setup, hi)
                && sp_canvas_paint_rect_internal(setup, lo);
        }
    }
}


Generated by  Doxygen 1.6.0   Back to index