Hide keyboard shortcuts

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. 

6 

7import cairo 

8from gi.repository import GLib #@UnresolvedImport 

9from gi.repository import GdkPixbuf #@UnresolvedImport 

10 

11from xpra.util import envbool 

12from xpra.client.gtk_base.cairo_backing_base import CairoBackingBase, FORMATS 

13 

14from xpra.log import Logger 

15log = Logger("paint", "cairo") 

16 

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 = {} 

26 

27 

28CAIRO_USE_PIXBUF = envbool("XPRA_CAIRO_USE_PIXBUF", False) 

29 

30 

31""" 

32An area we draw onto with cairo 

33This must be used with gtk3 since gtk3 no longer supports gdk pixmaps 

34 

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): 

41 

42 RGB_MODES = ["BGRA", "BGRX", "RGBA", "RGBX", "BGR", "RGB", "r210", "BGR565"] 

43 

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) 

51 

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) 

70 

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 

86 

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