def _do_paint_rgb(self, cairo_format, has_alpha, img_data, x, y, width, height, rowstride, options): """ must be called from UI thread """ log("cairo._do_paint_rgb(%s, %s, %s bytes,%s,%s,%s,%s,%s,%s)", cairo_format, has_alpha, len(img_data), x, y, width, height, rowstride, options) rgb_format = options.strget("rgb_format", "RGB") if rgb_format in ("ARGB", ): #the pixel format is also what cairo expects #maybe we should also check that the stride is acceptable for cairo? #cairo_stride = cairo.ImageSurface.format_stride_for_width(cairo_format, width) #log("cairo_stride=%s, stride=%s", cairo_stride, rowstride) pix_data = bytearray(img_data) img_surface = cairo.ImageSurface.create_for_data( pix_data, cairo_format, width, height, rowstride) self.cairo_paint_surface(img_surface, x, y, options) return True if rgb_format in ("RGBA", "RGBX", "RGB"): #with GTK2, we can use a pixbuf from RGB(A) pixels if rgb_format == "RGBA": #we have to unpremultiply for pixbuf! img_data = self.unpremultiply(img_data) #Pixbuf cannot use the memoryview directly: img_data = memoryview_to_bytes(img_data) pixbuf = pixbuf_new_from_data(img_data, COLORSPACE_RGB, has_alpha, 8, width, height, rowstride) self.cairo_paint_pixbuf(pixbuf, x, y, options) return True self.nasty_rgb_via_png_paint(cairo_format, has_alpha, img_data, x, y, width, height, rowstride, rgb_format) return True
def _do_paint_rgb(self, cairo_format, has_alpha, img_data, x, y, width, height, rowstride, options): """ must be called from UI thread """ log("cairo._do_paint_rgb(%s, %s, %s bytes,%s,%s,%s,%s,%s,%s)", cairo_format, has_alpha, len(img_data), x, y, width, height, rowstride, options) rgb_format = options.strget("rgb_format", "RGB") if rgb_format in ("ARGB", ): #the pixel format is also what cairo expects #maybe we should also check that the stride is acceptable for cairo? #cairo_stride = cairo.ImageSurface.format_stride_for_width(cairo_format, width) #log("cairo_stride=%s, stride=%s", cairo_stride, rowstride) pix_data = bytearray(img_data) img_surface = cairo.ImageSurface.create_for_data(pix_data, cairo_format, width, height, rowstride) self.cairo_paint_surface(img_surface, x, y) return True if rgb_format in ("RGBA", "RGBX", "RGB"): #with GTK2, we can use a pixbuf from RGB(A) pixels if rgb_format=="RGBA": #we have to unpremultiply for pixbuf! img_data = self.unpremultiply(img_data) #Pixbuf cannot use the memoryview directly: img_data = memoryview_to_bytes(img_data) pixbuf = pixbuf_new_from_data(img_data, COLORSPACE_RGB, has_alpha, 8, width, height, rowstride) self.cairo_paint_pixbuf(pixbuf, x, y) return True self.nasty_rgb_via_png_paint(cairo_format, has_alpha, img_data, x, y, width, height, rowstride, rgb_format) return True
def cairo_paint_pointer_overlay(context, cursor_data, px, py, start_time): if not cursor_data: return elapsed = max(0, monotonic_time() - start_time) if elapsed > 6: return cw = cursor_data[3] ch = cursor_data[4] xhot = cursor_data[5] yhot = cursor_data[6] pixels = cursor_data[8] x = px - xhot y = py - yhot alpha = max(0, (5.0 - elapsed) / 5.0) log("cairo_paint_pointer_overlay%s drawing pointer with cairo, alpha=%s", (context, x, y, start_time), alpha) context.translate(x, y) context.rectangle(0, 0, cw, ch) argb = unpremultiply_argb(pixels) img_data = memoryview_to_bytes(argb) pixbuf = pixbuf_new_from_data(img_data, COLORSPACE_RGB, True, 8, cw, ch, cw * 4) context.set_operator(cairo.OPERATOR_OVER) cairo_set_source_pixbuf(context, pixbuf, 0, 0) context.paint()
def _do_paint_rgb(self, cairo_format, has_alpha, img_data, x, y, width, height, rowstride, options): """ must be called from UI thread """ log("cairo._do_paint_rgb(%s, %s, %s bytes,%s,%s,%s,%s,%s,%s)", cairo_format, has_alpha, len(img_data), x, y, width, height, rowstride, options) rgb_format = options.strget("rgb_format", "RGB") if _memoryview and isinstance(img_data, _memoryview): #Pixbuf cannot use the memoryview directly: img_data = img_data.tobytes() #"cairo.ImageSurface.create_for_data" is not implemented in GTK3! ARGH! # http://cairographics.org/documentation/pycairo/3/reference/surfaces.html#cairo.ImageSurface.create_for_data # "Not yet available in Python 3" # #It is available in the cffi cairo bindings, which can be used instead of pycairo # but then we can't use it from the draw callbacks: # https://mail.gnome.org/archives/python-hackers-list/2011-December/msg00004.html # "PyGObject just lacks the glue code that allows it to pass the statically-wrapped # cairo.Pattern to introspected methods" if not is_gtk3() and rgb_format in ("ARGB", "XRGB"): #the pixel format is also what cairo expects #maybe we should also check that the stride is acceptable for cairo? #cairo_stride = cairo.ImageSurface.format_stride_for_width(cairo_format, width) #log("cairo_stride=%s, stride=%s", cairo_stride, rowstride) img_surface = cairo.ImageSurface.create_for_data( img_data, cairo_format, width, height, rowstride) return self.cairo_paint_surface(img_surface, x, y) if not is_gtk3() and rgb_format in ("RGBA", "RGBX"): #with GTK2, we can use a pixbuf from RGB(A) pixels if rgb_format == "RGBA": #we have to unpremultiply for pixbuf! img_data = self.unpremultiply(img_data) pixbuf = pixbuf_new_from_data(img_data, COLORSPACE_RGB, has_alpha, 8, width, height, rowstride) return self.cairo_paint_pixbuf(pixbuf, x, y) #PIL fallback PIL = get_codec("PIL") if has_alpha: oformat = "RGBA" else: oformat = "RGB" img = PIL.Image.frombuffer(oformat, (width, height), img_data, "raw", rgb_format, rowstride, 1) #This is insane, the code below should work, but it doesn't: # img_data = bytearray(img.tostring('raw', oformat, 0, 1)) # pixbuf = pixbuf_new_from_data(img_data, COLORSPACE_RGB, True, 8, width, height, rowstride) # success = self.cairo_paint_pixbuf(pixbuf, x, y) #So we still rountrip via PNG: png = BytesIOClass() img.save(png, format="PNG") reader = BytesIOClass(png.getvalue()) png.close() img = cairo.ImageSurface.create_from_png(reader) return self.cairo_paint_surface(img, x, y)
def set_icon_from_data(self, pixels, has_alpha, w, h, rowstride, options={}): tray_icon = pixbuf_new_from_data(pixels, COLORSPACE_RGB, has_alpha, 8, w, h, rowstride) self.macapp.set_dock_icon_pixbuf(tray_icon) self.icon_timestamp = monotonic_time()
def _do_paint_rgb(self, cairo_format, has_alpha, img_data, x, y, width, height, rowstride, options): """ must be called from UI thread """ log("cairo._do_paint_rgb(%s, %s, %s bytes,%s,%s,%s,%s,%s,%s)", cairo_format, has_alpha, len(img_data), x, y, width, height, rowstride, options) rgb_format = options.strget("rgb_format", "RGB") if _memoryview and isinstance(img_data, _memoryview): #Pixbuf cannot use the memoryview directly: img_data = img_data.tobytes() #"cairo.ImageSurface.create_for_data" is not implemented in GTK3! ARGH! # http://cairographics.org/documentation/pycairo/3/reference/surfaces.html#cairo.ImageSurface.create_for_data # "Not yet available in Python 3" # #It is available in the cffi cairo bindings, which can be used instead of pycairo # but then we can't use it from the draw callbacks: # https://mail.gnome.org/archives/python-hackers-list/2011-December/msg00004.html # "PyGObject just lacks the glue code that allows it to pass the statically-wrapped # cairo.Pattern to introspected methods" if not is_gtk3() and rgb_format in ("ARGB", "XRGB"): #the pixel format is also what cairo expects #maybe we should also check that the stride is acceptable for cairo? #cairo_stride = cairo.ImageSurface.format_stride_for_width(cairo_format, width) #log("cairo_stride=%s, stride=%s", cairo_stride, rowstride) img_surface = cairo.ImageSurface.create_for_data(img_data, cairo_format, width, height, rowstride) return self.cairo_paint_surface(img_surface, x, y) if not is_gtk3() and rgb_format in ("RGBA", "RGBX"): #with GTK2, we can use a pixbuf from RGB(A) pixels if rgb_format=="RGBA": #we have to unpremultiply for pixbuf! img_data = self.unpremultiply(img_data) pixbuf = pixbuf_new_from_data(img_data, COLORSPACE_RGB, has_alpha, 8, width, height, rowstride) return self.cairo_paint_pixbuf(pixbuf, x, y) #PIL fallback PIL = get_codec("PIL") if has_alpha: oformat = "RGBA" else: oformat = "RGB" img = PIL.Image.frombuffer(oformat, (width,height), img_data, "raw", rgb_format, rowstride, 1) #This is insane, the code below should work, but it doesn't: # img_data = bytearray(img.tostring('raw', oformat, 0, 1)) # pixbuf = pixbuf_new_from_data(img_data, COLORSPACE_RGB, True, 8, width, height, rowstride) # success = self.cairo_paint_pixbuf(pixbuf, x, y) #So we still rountrip via PNG: png = BytesIOClass() img.save(png, format="PNG") reader = BytesIOClass(png.getvalue()) png.close() img = cairo.ImageSurface.create_from_png(reader) return self.cairo_paint_surface(img, x, y)
def set_icon_from_data(self, pixels, has_alpha, w, h, rowstride, _options=None): #use a temporary file (yuk) from xpra.gtk_common.gtk_util import COLORSPACE_RGB, pixbuf_new_from_data import tempfile try: filename = tempfile.mkstemp(suffix=".png")[1] log("set_icon_from_data%s using temporary file %s", ("%s pixels" % len(pixels), has_alpha, w, h, rowstride), filename) tray_icon = pixbuf_new_from_data(pixels, COLORSPACE_RGB, has_alpha, 8, w, h, rowstride) tray_icon.save(filename, "png") self.do_set_icon_from_file(filename) finally: if DELETE_TEMP_FILE: os.unlink(filename)
def set_icon_from_data(self, pixels, has_alpha, w, h, rowstride, _options=None): self.clean_last_tmp_icon() #use a temporary file (yuk) from xpra.gtk_common.gtk_util import COLORSPACE_RGB, pixbuf_new_from_data, pixbuf_save_to_memory import tempfile tmp_dir = osexpand(get_xpra_tmp_dir()) if not os.path.exists(tmp_dir): os.mkdir(tmp_dir, 0o755) self.tmp_filename = tempfile.mkstemp(prefix="tray", suffix=".png", dir=tmp_dir)[1] log("set_icon_from_data%s using temporary file %s", ("%s pixels" % len(pixels), has_alpha, w, h, rowstride), self.tmp_filename) tray_icon = pixbuf_new_from_data(pixels, COLORSPACE_RGB, has_alpha, 8, w, h, rowstride) png_data = pixbuf_save_to_memory(tray_icon) with open(self.tmp_filename, "wb") as f: f.write(png_data) self.do_set_icon_from_file(self.tmp_filename)
def update_icon(self, width, height, coding, data): log("%s.update_icon(%s, %s, %s, %s bytes)", self, width, height, coding, len(data)) coding = bytestostr(coding) if coding == "premult_argb32": if unpremultiply_argb is None: #we could use PIL here with mode 'RGBa' log.warn("cannot process premult_argb32 icon without the argb module") return #we usually cannot do in-place and this is not performance critical data = byte_buffer_to_buffer(unpremultiply_argb(data)) pixbuf = pixbuf_new_from_data(data, COLORSPACE_RGB, True, 8, width, height, width*4) else: loader = PixbufLoader() loader.write(data) loader.close() pixbuf = loader.get_pixbuf() log("%s.set_icon(%s)", self, pixbuf) self.set_icon(pixbuf)
def update_icon(self, width, height, coding, data): log("%s.update_icon(%s, %s, %s, %s bytes)", self, width, height, coding, len(data)) coding = bytestostr(coding) if coding == "premult_argb32": if unpremultiply_argb is None: #we could use PIL here with mode 'RGBa' log.warn( "cannot process premult_argb32 icon without the argb module" ) return #we usually cannot do in-place and this is not performance critical data = byte_buffer_to_buffer(unpremultiply_argb(data)) pixbuf = pixbuf_new_from_data(data, COLORSPACE_RGB, True, 8, width, height, width * 4) else: loader = PixbufLoader() loader.write(data) loader.close() pixbuf = loader.get_pixbuf() log("%s.set_icon(%s)", self, pixbuf) self.set_icon(pixbuf)