예제 #1
0
static gboolean
get_selection_bounds (EvView          *view,
		      EvViewSelection *selection,
		      gint            *start_offset,
		      gint            *end_offset)
{
	cairo_rectangle_int_t rect;
	gint start, end;

	if (!selection->covered_region || cairo_region_is_empty (selection->covered_region))
		return FALSE;

	cairo_region_get_rectangle (selection->covered_region, 0, &rect);
	start = _ev_view_get_caret_cursor_offset_at_doc_point (view,
							       selection->page,
							       rect.x / view->scale,
							       (rect.y + (rect.height / 2)) / view->scale);
	if (start == -1)
		return FALSE;

	cairo_region_get_rectangle (selection->covered_region,
				    cairo_region_num_rectangles (selection->covered_region) - 1,
				    &rect);
	end = _ev_view_get_caret_cursor_offset_at_doc_point (view,
							     selection->page,
							     (rect.x + rect.width) / view->scale,
							     (rect.y + (rect.height / 2)) / view->scale);
	if (end == -1)
		return FALSE;

	*start_offset = start;
	*end_offset = end;

	return TRUE;
}
예제 #2
0
// cairo_public cairo_bool_t
// cairo_region_is_empty (const cairo_region_t *region);
static int l_cairo_region_is_empty (lua_State* L)
{
    const cairo_region_t *region = get_cairo_region_t (L, 1);
    cairo_bool_t v = cairo_region_is_empty (region);
    lua_pushboolean(L, v);
    return 1;
}
예제 #3
0
cairo_int_status_t
_cairo_clip_get_region (cairo_clip_t *clip,
			cairo_region_t **region)
{
    cairo_int_status_t status;

    if (clip->all_clipped)
	goto CLIPPED;

    assert (clip->path != NULL);

    status = _cairo_clip_path_to_region (clip->path);
    if (status)
	return status;

    if (cairo_region_is_empty (clip->path->region)) {
	_cairo_clip_set_all_clipped (clip);
	goto CLIPPED;
    }

    if (region)
	*region = clip->path->region;
    return CAIRO_STATUS_SUCCESS;

  CLIPPED:
    if (region)
	*region = NULL;
    return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
예제 #4
0
static gboolean
byzanz_recorder_snapshot (ByzanzRecorder *recorder)
{
  cairo_surface_t *surface;
  cairo_region_t *invalid;
  GTimeVal tv;

  if (!recorder->recording)
    return FALSE;

  if (recorder->next_image_source != 0)
    return FALSE;

  invalid = byzanz_recorder_get_invalid_region (recorder);
  if (cairo_region_is_empty (invalid)) {
    cairo_region_destroy (invalid);
    return FALSE;
  }

  surface = byzanz_recorder_create_snapshot (recorder, invalid);
  g_get_current_time (&tv);
  cairo_region_translate (invalid, -recorder->area.x, -recorder->area.y);

  g_signal_emit (recorder, signals[IMAGE], 0, surface, invalid, &tv);

  cairo_surface_destroy (surface);
  cairo_region_destroy (invalid);

  recorder->next_image_source = gdk_threads_add_timeout_full (G_PRIORITY_HIGH_IDLE,
      BYZANZ_RECORDER_FRAME_RATE_MS, byzanz_recorder_next_image, recorder, NULL);

  return TRUE;
}
예제 #5
0
파일: gskrenderer.c 프로젝트: GNOME/gtk
/**
 * gsk_renderer_render:
 * @renderer: a #GskRenderer
 * @root: a #GskRenderNode
 * @region: (nullable): the #cairo_region_t that must be redrawn or %NULL
 *     for the whole window
 *
 * Renders the scene graph, described by a tree of #GskRenderNode instances,
 * ensuring that the given @region gets redrawn.
 *
 * Renderers must ensure that changes of the contents given by the @root
 * node as well as the area given by @region are redrawn. They are however
 * free to not redraw any pixel outside of @region if they can guarantee that
 * it didn't change.
 *
 * The @renderer will acquire a reference on the #GskRenderNode tree while
 * the rendering is in progress.
 */
void
gsk_renderer_render (GskRenderer          *renderer,
                     GskRenderNode        *root,
                     const cairo_region_t *region)
{
  GskRendererPrivate *priv = gsk_renderer_get_instance_private (renderer);
  cairo_region_t *clip;

  g_return_if_fail (GSK_IS_RENDERER (renderer));
  g_return_if_fail (priv->is_realized);
  g_return_if_fail (GSK_IS_RENDER_NODE (root));
  g_return_if_fail (priv->root_node == NULL);

  if (region == NULL || priv->prev_node == NULL || GSK_RENDERER_DEBUG_CHECK (renderer, FULL_REDRAW))
    {
      clip = cairo_region_create_rectangle (&(GdkRectangle) {
                                                0, 0,
                                                gdk_surface_get_width (priv->surface),
                                                gdk_surface_get_height (priv->surface)
                                            });
    }
  else
    {
      clip = cairo_region_copy (region);
      gsk_render_node_diff (priv->prev_node, root, clip);

      if (cairo_region_is_empty (clip))
        {
          cairo_region_destroy (clip);
          return;
        }
    }

  priv->root_node = gsk_render_node_ref (root);

  GSK_RENDERER_GET_CLASS (renderer)->render (renderer, root, clip);

#ifdef G_ENABLE_DEBUG
  if (GSK_RENDERER_DEBUG_CHECK (renderer, RENDERER))
    {
      GString *buf = g_string_new ("*** Frame stats ***\n\n");

      gsk_profiler_append_counters (priv->profiler, buf);
      g_string_append_c (buf, '\n');

      gsk_profiler_append_timers (priv->profiler, buf);
      g_string_append_c (buf, '\n');

      g_print ("%s\n***\n\n", buf->str);

      g_string_free (buf, TRUE);
    }
#endif

  g_clear_pointer (&priv->prev_node, gsk_render_node_unref);
  cairo_region_destroy (clip);
  priv->prev_node = priv->root_node;
  priv->root_node = NULL;
}
예제 #6
0
bool wxRegion::IsEmpty() const
{
#ifdef __WXGTK3__
    return m_refData == NULL || cairo_region_is_empty(M_REGIONDATA->m_region);
#else
    return m_refData == NULL || gdk_region_empty(M_REGIONDATA->m_region);
#endif
}
예제 #7
0
파일: gtkpixelcache.c 프로젝트: Vort/gtk
static void
_gtk_pixel_cache_repaint (GtkPixelCache         *cache,
                          GdkWindow             *window,
                          GtkPixelCacheDrawFunc  draw,
                          cairo_rectangle_int_t *view_rect,
                          cairo_rectangle_int_t *canvas_rect,
                          gpointer               user_data)
{
  cairo_t *backing_cr;
  cairo_region_t *region_dirty = cache->surface_dirty;
  cache->surface_dirty = NULL;

  if (cache->surface &&
      region_dirty &&
      !cairo_region_is_empty (region_dirty))
    {
      backing_cr = cairo_create (cache->surface);
      gdk_cairo_region (backing_cr, region_dirty);
      cairo_clip (backing_cr);
      cairo_translate (backing_cr,
                       -cache->surface_x - canvas_rect->x - view_rect->x,
                       -cache->surface_y - canvas_rect->y - view_rect->y);

      cairo_save (backing_cr);
      cairo_set_source_rgba (backing_cr,
                             0.0, 0, 0, 0.0);
      cairo_set_operator (backing_cr, CAIRO_OPERATOR_SOURCE);
      cairo_paint (backing_cr);
      cairo_restore (backing_cr);

      cairo_save (backing_cr);
      draw (backing_cr, user_data);
      cairo_restore (backing_cr);

#ifdef G_ENABLE_DEBUG
      if (GTK_DISPLAY_DEBUG_CHECK (gdk_window_get_display (window), PIXEL_CACHE))
        {
          GdkRGBA colors[] = {
            { 1, 0, 0, 0.08},
            { 0, 1, 0, 0.08},
            { 0, 0, 1, 0.08},
            { 1, 0, 1, 0.08},
            { 1, 1, 0, 0.08},
            { 0, 1, 1, 0.08},
          };
          static int current_color = 0;

          gdk_cairo_set_source_rgba (backing_cr, &colors[(current_color++) % G_N_ELEMENTS (colors)]);
          cairo_paint (backing_cr);
        }
#endif

      cairo_destroy (backing_cr);
    }

  if (region_dirty)
    cairo_region_destroy (region_dirty);
}
예제 #8
0
gboolean
byzanz_serialize (GOutputStream *        stream,
                  guint64                msecs,
                  cairo_surface_t *      surface,
                  const cairo_region_t * region,
                  GCancellable *         cancellable,
                  GError **              error)
{
  guint i, stride;
  cairo_rectangle_int_t rect, extents;
  guchar *data;
  guint32 n;
  int y, n_rects;

  g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
  g_return_val_if_fail ((surface == NULL) == (region == NULL), FALSE);
  g_return_val_if_fail (region == NULL || !cairo_region_is_empty (region), FALSE);

  if (!g_output_stream_write_all (stream, &msecs, sizeof (guint64), NULL, cancellable, error))
    return FALSE;

  if (surface == 0) {
    n = 0;
    return g_output_stream_write_all (stream, &n, sizeof (guint32), NULL, cancellable, error);
  }

  n = n_rects = cairo_region_num_rectangles (region);
  if (!g_output_stream_write_all (stream, &n, sizeof (guint32), NULL, cancellable, error))
    return FALSE;
  for (i = 0; i < n; i++) {
    gint32 ints[4];
    cairo_region_get_rectangle (region, i, &rect);
    ints[0] = rect.x, ints[1] = rect.y, ints[2] = rect.width, ints[3] = rect.height;

    g_assert (sizeof (ints) == 16);
    if (!g_output_stream_write_all (stream, ints, sizeof (ints), NULL, cancellable, error))
      return FALSE;
  }

  stride = cairo_image_surface_get_stride (surface);
  cairo_region_get_extents (region, &extents);
  for (i = 0; i < n; i++) {
    cairo_region_get_rectangle (region, i, &rect);
    data = cairo_image_surface_get_data (surface) 
      + stride * (rect.y - extents.y) 
      + sizeof (guint32) * (rect.x - extents.x);
    for (y = 0; y < rect.height; y++) {
      if (!g_output_stream_write_all (G_OUTPUT_STREAM (stream), data, 
            rect.width * sizeof (guint32), NULL, cancellable, error))
        return FALSE;
      data += stride;
    }
  }

  return TRUE;
}
예제 #9
0
/* Region is in canvas coordinates */
void
_gtk_pixel_cache_invalidate (GtkPixelCache *cache,
			     cairo_region_t *region)
{
  cairo_rectangle_int_t r;
  cairo_region_t *free_region = NULL;

  if (cache->surface == NULL ||
      (region != NULL && cairo_region_is_empty (region)))
    return;

  if (region == NULL)
    {
      r.x = cache->surface_x;
      r.y = cache->surface_y;
      r.width = cache->surface_w;
      r.height = cache->surface_h;

      free_region = region =
	cairo_region_create_rectangle (&r);
    }

  if (cache->surface_dirty == NULL)
    {
      cache->surface_dirty = cairo_region_copy (region);
      cairo_region_translate (cache->surface_dirty,
			      -cache->surface_x,
			      -cache->surface_y);
    }
  else
    {
      cairo_region_translate (region,
			      -cache->surface_x,
			      -cache->surface_y);
      cairo_region_union (cache->surface_dirty, region);
      cairo_region_translate (region,
			      cache->surface_x,
			      cache->surface_y);
    }

  if (free_region)
    cairo_region_destroy (free_region);

  r.x = 0;
  r.y = 0;
  r.width = cache->surface_w;
  r.height = cache->surface_h;

  cairo_region_intersect_rectangle (cache->surface_dirty, &r);
}
예제 #10
0
파일: drawing.c 프로젝트: Guff/lualock
gboolean draw(gpointer data) {
    if (cairo_region_is_empty(lualock.updates_needed))
        return TRUE;
    cairo_rectangle_int_t extents;
    cairo_region_get_extents(lualock.updates_needed, &extents);
    cairo_t *cr = cairo_create(lualock.surface_buf);
    cairo_rectangle(cr, extents.x, extents.y, extents.width, extents.height);
    cairo_clip(cr);
    cairo_set_source_rgba(cr, 0, 0, 0, 0);
    cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
    cairo_paint(cr);
    cairo_set_operator(cr, CAIRO_OPERATOR_OVER);

    cairo_set_source_surface(cr, lualock.bg_surface, 0, 0);
    cairo_paint(cr);

    for (guint i = 0; i < lualock.layers->len; i++) {
        layer_t *layer = g_ptr_array_index(lualock.layers, i);
        if (!layer->show)
            continue;
        cairo_save(cr);
        cairo_translate(cr, layer->x, layer->y);
        cairo_scale(cr, layer->scale_x, layer->scale_y);
        cairo_rotate(cr, layer->angle);
        cairo_set_source_surface(cr, layer->surface, 0, 0);
        cairo_paint(cr);
        cairo_restore(cr);
    }
    draw_password_mask();
    cairo_translate(cr, lualock.style.x, lualock.style.y);
    cairo_set_source_surface(cr, lualock.pw_surface, 0, 0);
    cairo_paint(cr);
    cairo_destroy(cr);

    cairo_t *crw = gdk_cairo_create(lualock.win);
    cairo_set_source_surface(crw, lualock.surface_buf, 0, 0);
    cairo_set_operator(crw, CAIRO_OPERATOR_SOURCE);
    cairo_paint(crw);
    cairo_destroy(crw);

    clear_updates();
    return TRUE;
}
예제 #11
0
void
_gdk_x11_window_process_expose (GdkWindow    *window,
                                gulong        serial,
                                GdkRectangle *area)
{
  cairo_region_t *invalidate_region = cairo_region_create_rectangle (area);
  GdkX11Display *display_x11 = GDK_X11_DISPLAY (GDK_WINDOW_DISPLAY (window));

  if (display_x11->translate_queue)
    {
      GList *tmp_list = display_x11->translate_queue->head;

      while (tmp_list)
        {
          GdkWindowQueueItem *item = tmp_list->data;
          GList *next = tmp_list->next;

          /* an overflow-safe (serial < item->serial) */
          if (serial - item->serial > (gulong) G_MAXLONG)
            {
              if (item->window == window)
		cairo_region_subtract (invalidate_region, item->antiexpose_area);
            }
          else
            {
              queue_delete_link (display_x11->translate_queue, tmp_list);
              queue_item_free (item);
            }
          tmp_list = next;
        }
    }

  if (!cairo_region_is_empty (invalidate_region))
    _gdk_window_invalidate_for_expose (window, invalidate_region);

  cairo_region_destroy (invalidate_region);
}
예제 #12
0
static cairo_status_t
_combine_region (cairo_surface_t *surface,
		 const cairo_region_t *region,
		 const cairo_rectangle_int_t *extents)
{
    cairo_region_t clear_region;
    cairo_status_t status;

    _cairo_region_init_rectangle (&clear_region, extents);
    status = cairo_region_subtract (&clear_region, region);
    if (unlikely (status))
	return status;

    if (! cairo_region_is_empty (&clear_region)) {
	cairo_region_translate (&clear_region, -extents->x, -extents->y);
	status = _cairo_surface_fill_region (surface,
					     CAIRO_OPERATOR_CLEAR,
					     CAIRO_COLOR_TRANSPARENT,
					     &clear_region);
    }
    _cairo_region_fini (&clear_region);

    return status;
}
예제 #13
0
/* Warning: This call modifies the coordinates of traps */
static cairo_status_t
_clip_and_composite_trapezoids (const cairo_pattern_t *src,
				cairo_operator_t op,
				cairo_surface_t *dst,
				cairo_traps_t *traps,
				cairo_clip_t *clip,
				cairo_antialias_t antialias)
{
    cairo_status_t status;
    cairo_region_t *trap_region = NULL;
    cairo_region_t *clear_region = NULL;
    cairo_rectangle_int_t extents;
    cairo_composite_traps_info_t traps_info;

    if (_cairo_operator_bounded_by_mask (op) && traps->num_traps == 0)
        return CAIRO_STATUS_SUCCESS;

    status = _cairo_surface_get_extents (dst, &extents);
    if (unlikely (status))
        return status;

    status = _cairo_traps_extract_region (traps, &trap_region);
    if (status && status != CAIRO_INT_STATUS_UNSUPPORTED)
	return status;

    if (_cairo_operator_bounded_by_mask (op)) {
        cairo_rectangle_int_t trap_extents;

        if (trap_region) {
            status = _cairo_clip_intersect_to_region (clip, trap_region);
            if (unlikely (status))
                goto out;

            cairo_region_get_extents (trap_region, &trap_extents);
        } else {
            cairo_box_t trap_box;
            _cairo_traps_extents (traps, &trap_box);
            _cairo_box_round_to_rectangle (&trap_box, &trap_extents);
        }

        if (! _cairo_rectangle_intersect (&extents, &trap_extents)) {
	    status = CAIRO_STATUS_SUCCESS;
	    goto out;
	}

        status = _cairo_clip_intersect_to_rectangle (clip, &extents);
        if (unlikely (status))
            goto out;
    } else {
        cairo_surface_t *clip_surface = clip ? clip->surface : NULL;

        if (trap_region && !clip_surface) {
            /* If we optimize drawing with an unbounded operator to
             * _cairo_surface_fill_rectangles() or to drawing with a
             * clip region, then we have an additional region to clear.
             */
            clear_region = cairo_region_create_rectangle (&extents);

	    status = cairo_region_status (clear_region);
	    if (unlikely (status))
		goto out;

            status = _cairo_clip_intersect_to_region (clip, clear_region);
            if (unlikely (status))
                goto out;

            cairo_region_get_extents (clear_region, &extents);

            status = cairo_region_subtract (clear_region, trap_region);
            if (unlikely (status))
                goto out;

            if (cairo_region_is_empty (clear_region)) {
                cairo_region_destroy (clear_region);
		clear_region = NULL;
            }
        } else {
            status = _cairo_clip_intersect_to_rectangle (clip, &extents);
        }
    }

    if (unlikely (status))
        goto out;

    if (trap_region) {
        cairo_surface_t *clip_surface = clip ? clip->surface : NULL;

        if ((src->type == CAIRO_PATTERN_TYPE_SOLID ||
             op == CAIRO_OPERATOR_CLEAR) && !clip_surface) {
            const cairo_color_t *color;

            if (op == CAIRO_OPERATOR_CLEAR) {
                color = CAIRO_COLOR_TRANSPARENT;
            } else {
                color = &((cairo_solid_pattern_t *)src)->color;
            }

            /* Solid rectangles special case */
            status = _cairo_surface_fill_region (dst, op, color, trap_region);

            if (!status && clear_region) {
                status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
                                                     CAIRO_COLOR_TRANSPARENT,
                                                     clear_region);
	    }

            goto out;
        }

        if ((_cairo_operator_bounded_by_mask (op) &&
             op != CAIRO_OPERATOR_SOURCE) || !clip_surface) {
            /* For a simple rectangle, we can just use composite(), for more
             * rectangles, we have to set a clip region. The cost of rasterizing
             * trapezoids is pretty high for most backends currently, so it's
             * worthwhile even if a region is needed.
             *
             * If we have a clip surface, we set it as the mask; this only works
             * for bounded operators other than SOURCE; for unbounded operators,
             * clip and mask cannot be interchanged. For SOURCE, the operator
             * as implemented by the backends is different in its handling
             * of the mask then what we want.
             *
             * CAIRO_INT_STATUS_UNSUPPORTED will be returned if the region has
             * more than rectangle and the destination doesn't support clip
             * regions. In that case, we fall through.
             */
            status = _composite_trap_region (clip, src, op, dst,
                                             trap_region, &extents);

            if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
                if (!status && clear_region)
                    status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
                                                         CAIRO_COLOR_TRANSPARENT,
                                                         clear_region);
                goto out;
            }
        }
    }

    traps_info.traps = traps;
    traps_info.antialias = antialias;

    status = _clip_and_composite (clip, op, src,
                                  _composite_traps_draw_func,
                                  &traps_info, dst, &extents);

out:
    if (trap_region)
        cairo_region_destroy (trap_region);
    if (clear_region)
        cairo_region_destroy (clear_region);

    return status;
}
예제 #14
0
/* 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);
  }
}
예제 #15
0
파일: gdkgl.c 프로젝트: davidyang5405/gtk
/**
 * gdk_cairo_draw_from_gl:
 * @cr: a cairo context
 * @window: The window we're rendering for (not necessarily into)
 * @source: The GL ID of the source buffer
 * @source_type: The type of the @source
 * @buffer_scale: The scale-factor that the @source buffer is allocated for
 * @x: The source x position in @source to start copying from in GL coordinates
 * @y: The source y position in @source to start copying from in GL coordinates
 * @width: The width of the region to draw
 * @height: The height of the region to draw
 *
 * This is the main way to draw GL content in GTK+. It takes a render buffer ID
 * (@source_type == #GL_RENDERBUFFER) or a texture id (@source_type == #GL_TEXTURE)
 * and draws it onto @cr with an OVER operation, respecting the current clip.
 * The top left corner of the rectangle specified by @x, @y, @width and @height
 * will be drawn at the current (0,0) position of the cairo_t.
 *
 * This will work for *all* cairo_t, as long as @window is realized, but the
 * fallback implementation that reads back the pixels from the buffer may be
 * used in the general case. In the case of direct drawing to a window with
 * no special effects applied to @cr it will however use a more efficient
 * approach.
 *
 * For #GL_RENDERBUFFER the code will always fall back to software for buffers
 * with alpha components, so make sure you use #GL_TEXTURE if using alpha.
 *
 * Calling this may change the current GL context.
 *
 * Since: 3.16
 */
void
gdk_cairo_draw_from_gl (cairo_t              *cr,
                        GdkWindow            *window,
                        int                   source,
                        int                   source_type,
                        int                   buffer_scale,
                        int                   x,
                        int                   y,
                        int                   width,
                        int                   height)
{
    GdkGLContext *paint_context;
    cairo_surface_t *image;
    cairo_matrix_t matrix;
    int dx, dy, window_scale;
    gboolean trivial_transform;
    cairo_surface_t *group_target;
    GdkWindow *direct_window, *impl_window;
    guint framebuffer;
    int alpha_size = 0;
    cairo_region_t *clip_region;
    GdkGLContextPaintData *paint_data;

    impl_window = window->impl_window;

    window_scale = gdk_window_get_scale_factor (impl_window);

    paint_context = gdk_window_get_paint_gl_context (window, NULL);
    if (paint_context == NULL)
    {
        g_warning ("gdk_cairo_draw_gl_render_buffer failed - no paint context");
        return;
    }

    clip_region = gdk_cairo_region_from_clip (cr);

    gdk_gl_context_make_current (paint_context);
    paint_data = gdk_gl_context_get_paint_data (paint_context);

    if (paint_data->tmp_framebuffer == 0)
        glGenFramebuffersEXT (1, &paint_data->tmp_framebuffer);

    if (source_type == GL_RENDERBUFFER)
    {
        glBindRenderbuffer (GL_RENDERBUFFER, source);
        glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_ALPHA_SIZE,  &alpha_size);
    }
    else if (source_type == GL_TEXTURE)
    {
        glBindTexture (GL_TEXTURE_2D, source);

        glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_ALPHA_SIZE,  &alpha_size);
    }
    else
    {
        g_warning ("Unsupported gl source type %d\n", source_type);
        return;
    }

    group_target = cairo_get_group_target (cr);
    direct_window = cairo_surface_get_user_data (group_target, &direct_key);

    cairo_get_matrix (cr, &matrix);

    dx = matrix.x0;
    dy = matrix.y0;

    /* Trivial == integer-only translation */
    trivial_transform =
        (double)dx == matrix.x0 && (double)dy == matrix.y0 &&
        matrix.xx == 1.0 && matrix.xy == 0.0 &&
        matrix.yx == 0.0 && matrix.yy == 1.0;

    /* For direct paint of non-alpha renderbuffer, we can
       just do a bitblit */
    if ((_gdk_gl_flags & GDK_GL_SOFTWARE_DRAW_GL) == 0 &&
            source_type == GL_RENDERBUFFER &&
            alpha_size == 0 &&
            direct_window != NULL &&
            direct_window->current_paint.use_gl &&
            trivial_transform &&
            clip_region != NULL)
    {
        int unscaled_window_height;
        int i;

        /* Create a framebuffer with the source renderbuffer and
           make it the current target for reads */
        framebuffer = paint_data->tmp_framebuffer;
        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, framebuffer);
        glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                                      GL_RENDERBUFFER_EXT, source);
        glBindFramebufferEXT (GL_DRAW_FRAMEBUFFER_EXT, 0);

        /* Translate to impl coords */
        cairo_region_translate (clip_region, dx, dy);

        glEnable (GL_SCISSOR_TEST);

        gdk_window_get_unscaled_size (impl_window, NULL, &unscaled_window_height);
        glDrawBuffer (GL_BACK);

#define FLIP_Y(_y) (unscaled_window_height - (_y))

        for (i = 0; i < cairo_region_num_rectangles (clip_region); i++)
        {
            cairo_rectangle_int_t clip_rect, dest;

            cairo_region_get_rectangle (clip_region, i, &clip_rect);
            clip_rect.x *= window_scale;
            clip_rect.y *= window_scale;
            clip_rect.width *= window_scale;
            clip_rect.height *= window_scale;

            glScissor (clip_rect.x, FLIP_Y (clip_rect.y + clip_rect.height),
                       clip_rect.width, clip_rect.height);

            dest.x = dx * window_scale;
            dest.y = dy * window_scale;
            dest.width = width * window_scale / buffer_scale;
            dest.height = height * window_scale / buffer_scale;

            if (gdk_rectangle_intersect (&clip_rect, &dest, &dest))
            {
                int clipped_src_x = x + (dest.x - dx * window_scale);
                int clipped_src_y = y + (height - dest.height - (dest.y - dy * window_scale));
                glBlitFramebufferEXT(clipped_src_x, clipped_src_y,
                                     (clipped_src_x + dest.width), (clipped_src_y + dest.height),
                                     dest.x, FLIP_Y(dest.y + dest.height),
                                     dest.x + dest.width, FLIP_Y(dest.y),
                                     GL_COLOR_BUFFER_BIT, GL_NEAREST);
                if (impl_window->current_paint.flushed_region)
                {
                    cairo_rectangle_int_t flushed_rect;

                    flushed_rect.x = dest.x / window_scale;
                    flushed_rect.y = dest.y / window_scale;
                    flushed_rect.width = (dest.x + dest.width + window_scale - 1) / window_scale - flushed_rect.x;
                    flushed_rect.height = (dest.y + dest.height + window_scale - 1) / window_scale - flushed_rect.y;

                    cairo_region_union_rectangle (impl_window->current_paint.flushed_region,
                                                  &flushed_rect);
                    cairo_region_subtract_rectangle (impl_window->current_paint.need_blend_region,
                                                     &flushed_rect);
                }
            }
        }

        glDisable (GL_SCISSOR_TEST);

        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);

#undef FLIP_Y

    }
    /* For direct paint of alpha or non-alpha textures we can use texturing */
    else if ((_gdk_gl_flags & GDK_GL_SOFTWARE_DRAW_GL) == 0 &&
             source_type == GL_TEXTURE &&
             direct_window != NULL &&
             direct_window->current_paint.use_gl &&
             trivial_transform &&
             clip_region != NULL)
    {
        int unscaled_window_height;
        GLint texture_width;
        GLint texture_height;
        int i, n_rects, n_quads;
        GdkTexturedQuad *quads;
        cairo_rectangle_int_t clip_rect;

        /* Translate to impl coords */
        cairo_region_translate (clip_region, dx, dy);

        if (alpha_size != 0)
        {
            cairo_region_t *opaque_region, *blend_region;

            opaque_region = cairo_region_copy (clip_region);
            cairo_region_subtract (opaque_region, impl_window->current_paint.flushed_region);
            cairo_region_subtract (opaque_region, impl_window->current_paint.need_blend_region);

            if (!cairo_region_is_empty (opaque_region))
                gdk_gl_texture_from_surface (impl_window->current_paint.surface,
                                             opaque_region);

            blend_region = cairo_region_copy (clip_region);
            cairo_region_intersect (blend_region, impl_window->current_paint.need_blend_region);

            glEnable (GL_BLEND);
            if (!cairo_region_is_empty (blend_region))
                gdk_gl_texture_from_surface (impl_window->current_paint.surface,
                                             blend_region);

            cairo_region_destroy (opaque_region);
            cairo_region_destroy (blend_region);
        }

        glBindTexture (GL_TEXTURE_2D, source);

        glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH,  &texture_width);
        glGetTexLevelParameteriv (GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT,  &texture_height);

        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

        glEnable (GL_SCISSOR_TEST);

        gdk_window_get_unscaled_size (impl_window, NULL, &unscaled_window_height);

#define FLIP_Y(_y) (unscaled_window_height - (_y))

        cairo_region_get_extents (clip_region, &clip_rect);

        glScissor (clip_rect.x * window_scale, FLIP_Y ((clip_rect.y + clip_rect.height) * window_scale),
                   clip_rect.width * window_scale, clip_rect.height * window_scale);

        n_quads = 0;
        n_rects = cairo_region_num_rectangles (clip_region);
        quads = g_new (GdkTexturedQuad, n_rects);
        for (i = 0; i < n_rects; i++)
        {
            cairo_rectangle_int_t dest;

            cairo_region_get_rectangle (clip_region, i, &clip_rect);

            clip_rect.x *= window_scale;
            clip_rect.y *= window_scale;
            clip_rect.width *= window_scale;
            clip_rect.height *= window_scale;

            dest.x = dx * window_scale;
            dest.y = dy * window_scale;
            dest.width = width * window_scale / buffer_scale;
            dest.height = height * window_scale / buffer_scale;

            if (gdk_rectangle_intersect (&clip_rect, &dest, &dest))
            {
                int clipped_src_x = x + (dest.x - dx * window_scale);
                int clipped_src_y = y + (height - dest.height - (dest.y - dy * window_scale));
                GdkTexturedQuad quad = {
                    dest.x, FLIP_Y(dest.y),
                    dest.x + dest.width, FLIP_Y(dest.y + dest.height),
                    clipped_src_x / (float)texture_width, (clipped_src_y + dest.height) / (float)texture_height,
                    (clipped_src_x + dest.width) / (float)texture_width, clipped_src_y / (float)texture_height,
                };

                quads[n_quads++] = quad;

                if (impl_window->current_paint.flushed_region)
                {
                    cairo_rectangle_int_t flushed_rect;

                    flushed_rect.x = dest.x / window_scale;
                    flushed_rect.y = dest.y / window_scale;
                    flushed_rect.width = (dest.x + dest.width + window_scale - 1) / window_scale - flushed_rect.x;
                    flushed_rect.height = (dest.y + dest.height + window_scale - 1) / window_scale - flushed_rect.y;

                    cairo_region_union_rectangle (impl_window->current_paint.flushed_region,
                                                  &flushed_rect);
                    cairo_region_subtract_rectangle (impl_window->current_paint.need_blend_region,
                                                     &flushed_rect);
                }
            }
        }

        if (n_quads > 0)
            gdk_gl_texture_quads (paint_context, GL_TEXTURE_2D, n_quads, quads);

        g_free (quads);

        if (alpha_size != 0)
            glDisable (GL_BLEND);

#undef FLIP_Y

    }
    else
    {
        /* Software fallback */

        /* TODO: avoid reading back non-required data due to dest clip */
        image = cairo_surface_create_similar_image (cairo_get_target (cr),
                (alpha_size == 0) ? CAIRO_FORMAT_RGB24 : CAIRO_FORMAT_ARGB32,
                width, height);

        cairo_surface_set_device_scale (image, buffer_scale, buffer_scale);

        framebuffer = paint_data->tmp_framebuffer;
        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, framebuffer);

        if (source_type == GL_RENDERBUFFER)
        {
            /* Create a framebuffer with the source renderbuffer and
               make it the current target for reads */
            glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                                          GL_RENDERBUFFER_EXT, source);
        }
        else
        {
            glFramebufferTexture2DEXT (GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
                                       GL_TEXTURE_2D, source, 0);
        }

        glPixelStorei (GL_PACK_ALIGNMENT, 4);
        glPixelStorei (GL_PACK_ROW_LENGTH, cairo_image_surface_get_stride (image) / 4);

        glReadPixels (x, y, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV,
                      cairo_image_surface_get_data (image));

        glPixelStorei (GL_PACK_ROW_LENGTH, 0);

        glBindFramebufferEXT (GL_FRAMEBUFFER_EXT, 0);

        cairo_surface_mark_dirty (image);

        /* Invert due to opengl having different origin */
        cairo_scale (cr, 1, -1);
        cairo_translate (cr, 0, -height / buffer_scale);

        cairo_set_source_surface (cr, image, 0, 0);
        cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
        cairo_paint (cr);

        cairo_surface_destroy (image);
    }

    if (clip_region)
        cairo_region_destroy (clip_region);

}
예제 #16
0
static GeglTile *
gimp_tile_handler_projection_validate (GeglTileSource *source,
                                       GeglTile       *tile,
                                       gint            x,
                                       gint            y)
{
  GimpTileHandlerProjection *projection;
  cairo_region_t            *tile_region;
  cairo_rectangle_int_t      tile_rect;

  projection = GIMP_TILE_HANDLER_PROJECTION (source);

  if (cairo_region_is_empty (projection->dirty_region))
    return tile;

  tile_region = cairo_region_copy (projection->dirty_region);

  tile_rect.x      = x * projection->tile_width;
  tile_rect.y      = y * projection->tile_height;
  tile_rect.width  = projection->tile_width;
  tile_rect.height = projection->tile_height;

  cairo_region_intersect_rectangle (tile_region, &tile_rect);

  if (! cairo_region_is_empty (tile_region))
    {
      gint tile_bpp;
      gint tile_stride;
      gint n_rects;
      gint i;

      if (! tile)
        tile = gegl_tile_handler_create_tile (GEGL_TILE_HANDLER (source),
                                              x, y, 0);

      cairo_region_subtract_rectangle (projection->dirty_region, &tile_rect);

      tile_bpp    = babl_format_get_bytes_per_pixel (projection->format);
      tile_stride = tile_bpp * projection->tile_width;

      gegl_tile_lock (tile);

      n_rects = cairo_region_num_rectangles (tile_region);

#if 0
      g_printerr ("%d ", n_rects);
#endif

      for (i = 0; i < n_rects; i++)
        {
          cairo_rectangle_int_t blit_rect;

          cairo_region_get_rectangle (tile_region, i, &blit_rect);

#if 0
          g_printerr ("constructing projection at %d %d %d %d\n",
                      blit_rect.x,
                      blit_rect.y,
                      blit_rect.width,
                      blit_rect.height);
#endif

          gegl_node_blit (projection->graph, 1.0,
                          GEGL_RECTANGLE (blit_rect.x,
                                          blit_rect.y,
                                          blit_rect.width,
                                          blit_rect.height),
                          projection->format,
                          gegl_tile_get_data (tile) +
                          (blit_rect.y % projection->tile_height) * tile_stride +
                          (blit_rect.x % projection->tile_width)  * tile_bpp,
                          tile_stride,
                          GEGL_ABYSS_NONE);
        }

      gegl_tile_unlock (tile);
    }

  cairo_region_destroy (tile_region);

  return tile;
}
예제 #17
0
JOY_GNUC_HOT
void
joy_gfx3d_window_submit(JoyBubble *self, GFX3D_NATIVE_Display display,
                        GFX3D_NATIVE_Surface fb, cairo_region_t *area)
{
    g_return_if_fail(JOY_IS_GFX3D_WINDOW(self));
    g_return_if_fail(display);
    g_return_if_fail(fb);
    struct Private *priv = GET_PRIVATE(self);
    if (G_UNLIKELY(!priv->image)) {
        return;
    }
    gint x = joy_bubble_get_x(self);
    gint y = joy_bubble_get_y(self);
    cairo_region_intersect(priv->expose, priv->area);
    cairo_region_intersect(priv->expose, area);
    if (cairo_region_is_empty(priv->expose)) {
        return;
    }
    GFX3D_NATIVE_Surface surface =
        GFX3D_Image_Get_NATIVE_Surface(priv->image);
    gint n = cairo_region_num_rectangles(priv->expose);
    gdouble alpha = joy_bubble_get_alpha(self);
    if (1. == alpha) {
        GFX3D_NATIVE_Blit_Blend_Generic_Parms_t parameters = {
            {
                GFX3D_NATIVE_BLIT_BLEND_CONST_eOne,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eSourceColor,
                0,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eDestinationColor,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eInverseSourceAlpha,
                0,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eZero
            },
            {
                GFX3D_NATIVE_BLIT_BLEND_CONST_eOne,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eSourceAlpha,
                0,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eDestinationAlpha,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eInverseSourceAlpha,
                0,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eZero,
            },
            0,
            0,
            0,
            GFX3D_NATIVE_BLIT_FilterCoeffs_eNone,
            GFX3D_NATIVE_BLIT_FilterCoeffs_eNone,
            0,
            0
        };
        for (gint i = 0; i < n; ++i) {
            cairo_rectangle_int_t rect;
            cairo_region_get_rectangle(priv->expose, i, &rect);
            GFX3D_NATIVE_Rect dst = {
                rect.x + x,
                rect.y + y,
                rect.width,
                rect.height
            };
            GFX3D_NATIVE_Blit_Blend_Generic(display,
                                            fb, &dst,
                                            surface, (gpointer)&rect,
                                            fb, &dst,
                                            &parameters);
        }
    } else {
        GFX3D_NATIVE_Blit_Blend_Generic_Parms_t parameters = {
            {
                GFX3D_NATIVE_BLIT_BLEND_CONST_eConstantAlpha,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eSourceColor,
                0,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eDestinationColor,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eInverseSourceAlpha,
                0,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eZero
            },
            {
                GFX3D_NATIVE_BLIT_BLEND_CONST_eOne,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eSourceAlpha,
                0,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eDestinationAlpha,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eInverseSourceAlpha,
                0,
                GFX3D_NATIVE_BLIT_BLEND_CONST_eZero,
            },
            (gint)(0xff * alpha) << 24,
            0,
            0,
            GFX3D_NATIVE_BLIT_FilterCoeffs_eNone,
            GFX3D_NATIVE_BLIT_FilterCoeffs_eNone,
            0,
            0
        };
        for (gint i = 0; i < n; ++i) {
            cairo_rectangle_int_t rect;
            cairo_region_get_rectangle(priv->expose, i, &rect);
            GFX3D_NATIVE_Rect dst = {
                rect.x + x,
                rect.y + y,
                rect.width,
                rect.height
            };
            GFX3D_NATIVE_Blit_Blend_Generic(display,
                                            fb, &dst,
                                            surface, (gpointer)&rect,
                                            fb, &dst,
                                            &parameters);
        }
    }
    cairo_region_subtract(priv->expose, priv->expose);
}
예제 #18
0
파일: region.cpp 프로젝트: 499940913/moon
bool
Region::IsEmpty ()
{
	return cairo_region_is_empty (cairo_region);
}