Coverage for /home/antoine/projects/xpra-git/dist/python3/lib64/python/xpra/client/gtk3/cairo_backing.py : 44%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is part of Xpra.
2# Copyright (C) 2008 Nathaniel Smith <njs@pobox.com>
3# Copyright (C) 2012-2018 Antoine Martin <antoine@xpra.org>
4# Xpra is released under the terms of the GNU GPL v2, or, at your option, any
5# later version. See the file COPYING for details.
7import cairo
8from gi.repository import GLib #@UnresolvedImport
9from gi.repository import GdkPixbuf #@UnresolvedImport
11from xpra.util import envbool
12from xpra.client.gtk_base.cairo_backing_base import CairoBackingBase, FORMATS
14from xpra.log import Logger
15log = Logger("paint", "cairo")
17try:
18 from xpra.client.gtk3.cairo_workaround import set_image_surface_data, CAIRO_FORMATS #@UnresolvedImport
19except ImportError as e:
20 log.warn("Warning: failed to load the gtk3 cairo workaround:")
21 log.warn(" %s", e)
22 log.warn(" rendering will be slow!")
23 del e
24 set_image_surface_data = None
25 CAIRO_FORMATS = {}
28CAIRO_USE_PIXBUF = envbool("XPRA_CAIRO_USE_PIXBUF", False)
31"""
32An area we draw onto with cairo
33This must be used with gtk3 since gtk3 no longer supports gdk pixmaps
35/RANT: ideally we would want to use pycairo's create_for_data method:
36#surf = cairo.ImageSurface.create_for_data(data, cairo.FORMAT_RGB24, width, height)
37but this is disabled in most cases, or does not accept our rowstride, so we cannot use it.
38Instead we have to use PIL to convert via a PNG or Pixbuf!
39"""
40class CairoBacking(CairoBackingBase):
42 RGB_MODES = ["BGRA", "BGRX", "RGBA", "RGBX", "BGR", "RGB", "r210", "BGR565"]
44 def __repr__(self):
45 b = self._backing
46 if b:
47 binfo = "ImageSurface(%i, %i)" % (b.get_width(), b.get_height())
48 else:
49 binfo = "None"
50 return "gtk3.CairoBacking(%s : size=%s, render_size=%s)" % (binfo, self.size, self.render_size)
52 def _do_paint_rgb(self, cairo_format, has_alpha, img_data,
53 x : int, y : int, width : int, height : int, render_width : int, render_height : int,
54 rowstride : int, options):
55 """ must be called from UI thread """
56 log("cairo._do_paint_rgb(%s, %s, %s %s, %s, %s, %s, %s, %s, %s, %s, %s) set_image_surface_data=%s, use pixbuf=%s",
57 FORMATS.get(cairo_format, cairo_format), has_alpha, len(img_data),
58 type(img_data), x, y, width, height, render_width, render_height,
59 rowstride, options, set_image_surface_data, CAIRO_USE_PIXBUF)
60 rgb_format = options.strget(b"rgb_format", "RGB")
61 if set_image_surface_data and not CAIRO_USE_PIXBUF:
62 rgb_formats = CAIRO_FORMATS.get(cairo_format)
63 if rgb_format in rgb_formats:
64 img_surface = cairo.ImageSurface(cairo_format, width, height)
65 set_image_surface_data(img_surface, rgb_format, img_data, width, height, rowstride)
66 self.cairo_paint_surface(img_surface, x, y, render_width, render_height, options)
67 return True
68 log("cannot set image surface data for cairo format %s and rgb_format %s (rgb formats supported: %s)",
69 cairo_format, rgb_format, rgb_formats)
71 if rgb_format in ("RGB", "RGBA", "RGBX"):
72 data = GLib.Bytes(img_data)
73 pixbuf = GdkPixbuf.Pixbuf.new_from_bytes(data, GdkPixbuf.Colorspace.RGB,
74 has_alpha, 8, width, height, rowstride)
75 if render_width!=width or render_height!=height:
76 resample = options.strget("resample")
77 if resample=="NEAREST":
78 interp_type = GdkPixbuf.InterpType.NEAREST
79 elif resample in ("BICUBIC", "LANCZOS"):
80 interp_type = GdkPixbuf.InterpType.HYPER
81 else:
82 interp_type = GdkPixbuf.InterpType.BILINEAR
83 pixbuf = pixbuf.scale_simple(render_width, render_height, interp_type)
84 self.cairo_paint_pixbuf(pixbuf, x, y, options)
85 return True
87 img_data = memoryview(img_data)
88 self.nasty_rgb_via_png_paint(cairo_format, has_alpha, img_data, x, y, width, height, rowstride, rgb_format)
89 return True