static cairo_int_status_t _cairo_gl_composite_setup_clipping (cairo_gl_composite_t *setup, cairo_gl_context_t *ctx, int vertex_size) { if (! _cairo_gl_context_is_flushed (ctx) && (! cairo_region_equal (ctx->clip_region, setup->clip_region) || ! _cairo_clip_equal (ctx->clip, setup->clip))) _cairo_gl_composite_flush (ctx); cairo_region_destroy (ctx->clip_region); ctx->clip_region = cairo_region_reference (setup->clip_region); _cairo_clip_destroy (ctx->clip); ctx->clip = _cairo_clip_copy (setup->clip); assert (!setup->clip_region || !setup->clip); if (ctx->clip_region) { _disable_stencil_buffer (); glEnable (GL_SCISSOR_TEST); return CAIRO_INT_STATUS_SUCCESS; } if (ctx->clip) return _cairo_gl_composite_setup_painted_clipping (setup, ctx, vertex_size); _disable_stencil_buffer (); glDisable (GL_SCISSOR_TEST); return CAIRO_INT_STATUS_SUCCESS; }
// cairo_public cairo_bool_t // cairo_region_equal (const cairo_region_t *a, const cairo_region_t *b); static int l_cairo_region_equal (lua_State* L) { const cairo_region_t *a = get_cairo_region_t (L, 1); const cairo_region_t *b = get_cairo_region_t (L, 2); cairo_bool_t v = cairo_region_equal (a, b); lua_pushboolean(L, v); return 1; }
bool wxRegion::DoIsEqual(const wxRegion& region) const { #ifdef __WXGTK3__ return cairo_region_equal( M_REGIONDATA->m_region, M_REGIONDATA_OF(region)->m_region); #else return gdk_region_equal(M_REGIONDATA->m_region, M_REGIONDATA_OF(region)->m_region) != 0; #endif }
static cairo_int_status_t _cairo_gl_composite_setup_clipping (cairo_gl_composite_t *setup, cairo_gl_context_t *ctx, int vertex_size) { cairo_bool_t clip_changing = TRUE; cairo_bool_t clip_region_changing = TRUE; if (! ctx->clip && ! setup->clip && ! setup->clip_region && ! ctx->clip_region) goto disable_all_clipping; clip_changing = ! _cairo_clip_equal (ctx->clip, setup->clip); clip_region_changing = ! cairo_region_equal (ctx->clip_region, setup->clip_region); if (! _cairo_gl_context_is_flushed (ctx) && (clip_region_changing || clip_changing)) _cairo_gl_composite_flush (ctx); assert (!setup->clip_region || !setup->clip); /* setup->clip is only used by the msaa compositor and setup->clip_region * only by the other compositors, so it's safe to wait to clean up obsolete * clips. */ if (clip_region_changing) { cairo_region_destroy (ctx->clip_region); ctx->clip_region = cairo_region_reference (setup->clip_region); } if (clip_changing) { _cairo_clip_destroy (ctx->clip); ctx->clip = _cairo_clip_copy (setup->clip); } /* For clip regions, we scissor right before drawing. */ if (setup->clip_region) goto disable_all_clipping; if (setup->clip) return _cairo_gl_composite_setup_painted_clipping (setup, ctx, vertex_size); disable_all_clipping: _disable_stencil_buffer (); glDisable (GL_SCISSOR_TEST); return CAIRO_INT_STATUS_SUCCESS; }
/* We double buffer the image. It looks nice and it enables * grabbing the graph with the pointer and translating it. * We draw on our own larger surface and then copy part of that * to the gdk surface. * * We assume that this function is drawing to an exposed/showing * drawing area, so the status update will reflect the current * exposed/showing drawing area. */ void qp_graph_draw(struct qp_graph *gr, cairo_t *gdk_cr) { GtkAllocation allocation; if(gr->waiting_to_resize_draw && !gr->qp->shape) { //WARN("gr=%p gr->name=\"%s\" gr->ref_count=%d\n", gr, gr->name, gr->ref_count); cairo_set_source_rgba(gdk_cr, gr->background_color.r, gr->background_color.g, gr->background_color.b, gr->background_color.a); cairo_paint(gdk_cr); g_idle_add_full(G_PRIORITY_LOW, idle_callback, gr, NULL); /* fight qp_graph_destroy() race condition with flag */ ++gr->ref_count; /* We draw after the other widgets are drawn, in case drawing * takes a long time. This waiting also gives a chance * for the watch cursor to show. But that seems to only * show if the window had focus at the right time. */ return; } gtk_widget_get_allocation(gr->drawing_area, &allocation); if(gr->pixbuf_needs_draw) { cairo_t *db_cr; /* double buffer cr */ db_cr = cairo_create(gr->pixbuf_surface); graph_draw(gr, db_cr, gr->pixbuf_x, gr->pixbuf_y, gr->pixbuf_width, gr->pixbuf_height); cairo_destroy(db_cr); // debuging //cairo_surface_write_to_png(gr->pixbuf_surface, "x.png"); qp_win_set_status(gr->qp); } /* the GTK cairo_t *gdk_cr has no alpha bits so all the * alpha drawn to it will be smushed. */ //WARN("content=0x%lx\n", (unsigned long)cairo_get_target(gdk_cr)); if(!gr->qp->shape) { /* Not using the shape X11 extension */ /* This is where we go from the back buffer to the drawing area */ draw_from_pixbuf(gdk_cr, gr, allocation.width, allocation.height); if(gr->draw_zoom_box == 1) draw_zoom_box(gdk_cr, gr); if(gr->draw_value_pick) draw_value_pick_line(gdk_cr, gr, allocation.width, allocation.height); if(gr->pixbuf_needs_draw) { gdk_window_set_cursor(gtk_widget_get_window(gr->qp->window), NULL); gr->pixbuf_needs_draw = 0; // gr->qp->wait_warning_showing = 0; } } else { /* Use the X11 shape extension */ /* TODO: This is a resource pig. Fix it. */ cairo_region_t *reg_draw_area, *window_region; /* empty flag */ int empty; cairo_surface_t *mask_surface; GtkAllocation all; /* Make sure the surface is up to date */ //cairo_surface_flush(gr->pixbuf_surface); /* make a sub surface that is the size of the graph drawing area */ mask_surface = cairo_surface_create_for_rectangle(gr->pixbuf_surface, INT(gr->pixbuf_x+gr->grab_x), INT(gr->pixbuf_y+gr->grab_y), allocation.width, allocation.height); reg_draw_area = get_cairo_region_create_from_surface(gr, mask_surface, allocation.width, allocation.height); cairo_surface_destroy(mask_surface); cairo_region_translate(reg_draw_area, allocation.x, allocation.y); gtk_widget_get_allocation(gr->qp->window, &all); all.x = all.y = 0; window_region = cairo_region_create_rectangle(&all); cairo_region_subtract_rectangle(window_region, &allocation); empty = cairo_region_is_empty(reg_draw_area); if(!empty) cairo_region_union(window_region, reg_draw_area); cairo_region_destroy(reg_draw_area); /* window_region is a region with a hole in it the * size of the drawing area with the graph and grid added back. */ if(gr->draw_zoom_box && !empty) { cairo_rectangle_int_t rec; rec.x = allocation.x + gr->z_x; rec.y = allocation.y + gr->z_y; rec.width = gr->z_w; rec.height = gr->z_h; /* regions do not like negitive values or * maybe shapes do not like negitive values * in any case we keep width and height * positive */ if(rec.width < 0) { rec.width *= -1; rec.x -= rec.width; } if(rec.height < 0) { rec.height *= -1; rec.y -= rec.height; } cairo_region_union_rectangle(window_region, &rec); /* now we have the zoom box added to window_region */ } /* This is where we go from the back buffer to the drawing area */ draw_from_pixbuf(gdk_cr, gr, allocation.width, allocation.height); if(gr->draw_zoom_box) draw_zoom_box(gdk_cr, gr); if(gr->draw_value_pick) draw_value_pick_line(gdk_cr, gr, allocation.width, allocation.height); if(empty) { /* we have nothing to make a shape with */ if(gr->qp->last_shape_region) { cairo_region_destroy(gr->qp->last_shape_region); gr->qp->last_shape_region = NULL; } cairo_region_destroy(window_region); /* remove the old shape region */ gtk_widget_shape_combine_region(gr->qp->window, NULL); } else if(!gr->qp->last_shape_region || !cairo_region_equal(gr->qp->last_shape_region, window_region)) { // DEBUG("creating new shape region\n"); /* We need to undo the old shape first */ gtk_widget_shape_combine_region(gr->qp->window, NULL); gtk_widget_shape_combine_region(gr->qp->window, window_region); if(gr->qp->last_shape_region) cairo_region_destroy(gr->qp->last_shape_region); gr->qp->last_shape_region = window_region; } else cairo_region_destroy(window_region); gr->pixbuf_needs_draw = 0; gdk_window_set_cursor(gtk_widget_get_window(gr->qp->window), NULL); // debuging //cairo_surface_write_to_png(cairo_get_target(gdk_cr), "y.png"); } if(gr->qp->update_graph_detail && gr->qp->graph_detail) { gr->qp->update_graph_detail = 0; /* make the graph configure window show stuff about this graph */ qp_win_graph_detail_init(gr->qp); } }
cairo_status_t _cairo_gl_composite_begin (cairo_gl_composite_t *setup, cairo_gl_context_t **ctx_out) { unsigned int dst_size, src_size, mask_size, vertex_size; cairo_gl_context_t *ctx; cairo_status_t status; cairo_bool_t component_alpha; cairo_gl_shader_t *shader; assert (setup->dst); status = _cairo_gl_context_acquire (setup->dst->base.device, &ctx); if (unlikely (status)) return status; glEnable (GL_BLEND); component_alpha = setup->mask.type == CAIRO_GL_OPERAND_TEXTURE && setup->mask.texture.attributes.has_component_alpha; /* Do various magic for component alpha */ if (component_alpha) { status = _cairo_gl_composite_begin_component_alpha (ctx, setup); if (unlikely (status)) goto FAIL; } else { if (ctx->pre_shader) { _cairo_gl_composite_flush (ctx); ctx->pre_shader = NULL; } } status = _cairo_gl_get_shader_by_type (ctx, &setup->src, &setup->mask, setup->spans, component_alpha ? CAIRO_GL_SHADER_IN_CA_SOURCE : CAIRO_GL_SHADER_IN_NORMAL, &shader); if (unlikely (status)) { ctx->pre_shader = NULL; goto FAIL; } if (ctx->current_shader != shader) _cairo_gl_composite_flush (ctx); status = CAIRO_STATUS_SUCCESS; dst_size = 2 * sizeof (GLfloat); src_size = _cairo_gl_operand_get_vertex_size (setup->src.type); mask_size = _cairo_gl_operand_get_vertex_size (setup->mask.type); vertex_size = dst_size + src_size + mask_size; if (setup->spans) vertex_size += sizeof (GLfloat); if (ctx->vertex_size != vertex_size) _cairo_gl_composite_flush (ctx); _cairo_gl_context_set_destination (ctx, setup->dst); if (_cairo_gl_context_is_flushed (ctx)) { ctx->dispatch.BindBuffer (GL_ARRAY_BUFFER, ctx->vbo); ctx->dispatch.VertexAttribPointer (CAIRO_GL_VERTEX_ATTRIB_INDEX, 2, GL_FLOAT, GL_FALSE, vertex_size, NULL); ctx->dispatch.EnableVertexAttribArray (CAIRO_GL_VERTEX_ATTRIB_INDEX); } _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_SOURCE, &setup->src, vertex_size, dst_size); _cairo_gl_context_setup_operand (ctx, CAIRO_GL_TEX_MASK, &setup->mask, vertex_size, dst_size + src_size); if (setup->spans) _cairo_gl_context_setup_spans (ctx, vertex_size, dst_size + src_size + mask_size); else ctx->dispatch.DisableVertexAttribArray (CAIRO_GL_COLOR_ATTRIB_INDEX); _cairo_gl_set_operator (ctx, setup->op, component_alpha); ctx->vertex_size = vertex_size; if (_cairo_gl_context_is_flushed (ctx)) { if (ctx->pre_shader) { _cairo_gl_set_shader (ctx, ctx->pre_shader); _cairo_gl_composite_bind_to_shader (ctx, setup); } _cairo_gl_set_shader (ctx, shader); _cairo_gl_composite_bind_to_shader (ctx, setup); } if (! _cairo_gl_context_is_flushed (ctx) && ! cairo_region_equal (ctx->clip_region, setup->clip_region)) _cairo_gl_composite_flush (ctx); cairo_region_destroy (ctx->clip_region); ctx->clip_region = cairo_region_reference (setup->clip_region); if (ctx->clip_region) glEnable (GL_SCISSOR_TEST); else glDisable (GL_SCISSOR_TEST); *ctx_out = ctx; FAIL: if (unlikely (status)) status = _cairo_gl_context_release (ctx, status); return status; }
static gboolean goc_canvas_draw (GtkWidget *widget, cairo_t *cr) { double x0, y0, x1, y1; double ax0, ay0, ax1, ay1; double clip_x1, clip_y1, clip_x2, clip_y2; GocCanvas *canvas = GOC_CANVAS (widget); GdkEventExpose *event = (GdkEventExpose *) gtk_get_current_event (); GocCanvasPrivate *priv = (GocCanvasPrivate *) canvas->priv; cairo_rectangle_list_t *l = cairo_copy_clip_rectangle_list (cr); int i, x, y; if (GOC_IS_ITEM (priv->invalidated_item) && priv->invalid_region) { /* evaluate the cairo clipped region and compare with the saved one */ cairo_region_t *region; cairo_rectangle_int_t rect[l->num_rectangles]; for (i= 0; i < l->num_rectangles; i++) { rect[i].x = l->rectangles[i].x; rect[i].y = l->rectangles[i].y; rect[i].width = l->rectangles[i].width; rect[i].height = l->rectangles[i].height; } region = cairo_region_create_rectangles (rect, l->num_rectangles); if (cairo_region_equal (priv->invalid_region, region)) { cairo_rectangle_list_destroy (l); cairo_region_destroy (region); /* looks like each time we call gtk_widget_queue_draw*, the draw event is fired twice */ if (priv->done) { priv->invalidated_item = NULL; cairo_region_destroy (priv->invalid_region); priv->invalid_region = NULL; } else { goc_item_draw (priv->invalidated_item, cr); priv->done = TRUE; } return TRUE; } cairo_region_destroy (region); } x = gtk_adjustment_get_value (gtk_scrollable_get_hadjustment (GTK_SCROLLABLE (canvas))); y = gtk_adjustment_get_value (gtk_scrollable_get_vadjustment (GTK_SCROLLABLE (canvas))); cairo_translate (cr, -x, -y); goc_item_get_bounds (GOC_ITEM (canvas->root),&x0, &y0, &x1, &y1); for (i= 0; i < l->num_rectangles; i++) { cairo_save (cr); cairo_rectangle (cr, l->rectangles[i].x, l->rectangles[i].y, l->rectangles[i].width, l->rectangles[i].height); cairo_clip (cr); clip_x1 = l->rectangles[i].x; clip_y1 = l->rectangles[i].y; clip_x2 = clip_x1 + l->rectangles[i].width; clip_y2 = clip_y1 + l->rectangles[i].height; if (canvas->direction == GOC_DIRECTION_RTL) { ax1 = (double) (canvas->width - clip_x1) / canvas->pixels_per_unit + canvas->scroll_x1; ax0 = (double) (canvas->width - clip_x2) / canvas->pixels_per_unit + canvas->scroll_x1; } else { ax0 = (double) clip_x1 / canvas->pixels_per_unit + canvas->scroll_x1; ax1 = ((double) clip_x1 + event->area.width) / canvas->pixels_per_unit + canvas->scroll_x1; } ay0 = (double) clip_y1 / canvas->pixels_per_unit + canvas->scroll_y1; ay1 = (double) clip_y2 / canvas->pixels_per_unit + canvas->scroll_y1; if (x0 <= ax1 && x1 >= ax0 && y0 <= ay1 && y1 >= ay0) { canvas->cur_event = (GdkEvent *) event; goc_item_draw_region (GOC_ITEM (canvas->root), cr, ax0, ay0, ax1, ay1); } cairo_restore (cr); } cairo_rectangle_list_destroy (l); return TRUE; }