gdkcairocontext-x11.c 4.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/* GDK - The GIMP Drawing Kit
 *
 * gdkcairocontext-x11.c: X11 specific Cairo wrappers
 *
 * Copyright © 2016  Benjamin Otte
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
 */

#include "config.h"

#include "gdkcairocontext-x11.h"

25 26 27 28 29 30 31
#include "gdkprivate-x11.h"

#include "gdkcairo.h"
#include "gdkinternals.h"

#include <X11/Xlib.h>

32 33
G_DEFINE_TYPE (GdkX11CairoContext, gdk_x11_cairo_context, GDK_TYPE_CAIRO_CONTEXT)

34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
static cairo_surface_t *
create_cairo_surface_for_surface (GdkSurface *surface)
{
  GdkDisplay *display;
  cairo_surface_t *cairo_surface;
  Visual *visual;
  int scale;
    
  display = gdk_surface_get_display (surface);
  scale = gdk_surface_get_scale_factor (surface);

  visual = gdk_x11_display_get_window_visual (GDK_X11_DISPLAY (display));
  cairo_surface = cairo_xlib_surface_create (gdk_x11_display_get_xdisplay (display),
                                             GDK_SURFACE_XID (surface),
                                             visual,
                                             gdk_surface_get_width (surface) * scale,
                                             gdk_surface_get_height (surface) * scale);
  cairo_surface_set_device_scale (cairo_surface, scale, scale);

  return cairo_surface;
}

static void
gdk_x11_cairo_context_begin_frame (GdkDrawContext *draw_context,
                                   cairo_region_t *region)
{
  GdkX11CairoContext *self = GDK_X11_CAIRO_CONTEXT (draw_context);
  GdkRectangle clip_box;
  GdkSurface *surface;
  double sx, sy;

  surface = gdk_draw_context_get_surface (draw_context);
  cairo_region_get_extents (region, &clip_box);

  self->window_surface = create_cairo_surface_for_surface (surface);
  self->paint_surface = gdk_surface_create_similar_surface (surface,
                                                            cairo_surface_get_content (self->window_surface),
                                                            MAX (clip_box.width, 1),
                                                            MAX (clip_box.height, 1));

  sx = sy = 1;
  cairo_surface_get_device_scale (self->paint_surface, &sx, &sy);
  cairo_surface_set_device_offset (self->paint_surface, -clip_box.x*sx, -clip_box.y*sy);
}

static void
gdk_x11_cairo_context_end_frame (GdkDrawContext *draw_context,
81
                                 cairo_region_t *painted)
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
{
  GdkX11CairoContext *self = GDK_X11_CAIRO_CONTEXT (draw_context);
  cairo_t *cr;

  cr = cairo_create (self->window_surface);

  cairo_set_source_surface (cr, self->paint_surface, 0, 0);
  gdk_cairo_region (cr, painted);
  cairo_clip (cr);

  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
  cairo_paint (cr);

  cairo_destroy (cr);

  cairo_surface_flush (self->window_surface);

  g_clear_pointer (&self->paint_surface, cairo_surface_destroy);
  g_clear_pointer (&self->window_surface, cairo_surface_destroy);
}

static cairo_t *
gdk_x11_cairo_context_cairo_create (GdkCairoContext *context)
{
  GdkX11CairoContext *self = GDK_X11_CAIRO_CONTEXT (context);

  return cairo_create (self->paint_surface);
}

111 112 113
static void
gdk_x11_cairo_context_class_init (GdkX11CairoContextClass *klass)
{
114 115 116 117 118 119 120
  GdkDrawContextClass *draw_context_class = GDK_DRAW_CONTEXT_CLASS (klass);
  GdkCairoContextClass *cairo_context_class = GDK_CAIRO_CONTEXT_CLASS (klass);

  draw_context_class->begin_frame = gdk_x11_cairo_context_begin_frame;
  draw_context_class->end_frame = gdk_x11_cairo_context_end_frame;

  cairo_context_class->cairo_create = gdk_x11_cairo_context_cairo_create;
121 122 123 124 125 126 127
}

static void
gdk_x11_cairo_context_init (GdkX11CairoContext *self)
{
}