def digAHole(self, svgShape, width, height): # FIXME # For Python 2.x pycairo does not support/implement cairo.Region() # https://bugs.launchpad.net/ubuntu/+source/pygobject/+bug/1028115/comments/8 return # Create a bitmap and clear it mask = cairo.ImageSurface(cairo.FORMAT_A1, width, height) mcontext = cairo.Context(mask) mcontext.set_source_rgb(0, 0, 0) mcontext.set_operator(cairo.OPERATOR_DEST_OUT) mcontext.paint() # Paint our shape surface = self.getSurfaceFromSvg(svgShape, width, height) mcontext.set_operator(cairo.OPERATOR_OVER) mcontext.set_source_surface(surface, 0, 0) mcontext.paint() # Apply it only if aren't composited, in which case we only need input # masking try: mregion = Gdk.cairo_region_create_from_surface(mask) except TypeError: return if self.is_composited(): self.get_window().input_shape_combine_region(mregion, 0, 0) else: self.get_window().shape_combine_region(mregion, 0, 0)
def digAHole (self, svgShape, width, height): # FIXME # For Python 2.x pycairo does not support/implement cairo.Region() # https://bugs.launchpad.net/ubuntu/+source/pygobject/+bug/1028115/comments/8 return # Create a bitmap and clear it mask = cairo.ImageSurface(cairo.FORMAT_A1, width, height) mcontext = cairo.Context(mask) mcontext.set_source_rgb(0, 0, 0) mcontext.set_operator(cairo.OPERATOR_DEST_OUT) mcontext.paint() # Paint our shape surface = self.getSurfaceFromSvg(svgShape, width, height) mcontext.set_operator(cairo.OPERATOR_OVER) mcontext.set_source_surface(surface, 0, 0) mcontext.paint() # Apply it only if aren't composited, in which case we only need input # masking try: mregion = Gdk.cairo_region_create_from_surface(mask) except TypeError: return if self.is_composited(): self.get_window().input_shape_combine_region(mregion, 0, 0) else: self.get_window().shape_combine_region(mregion, 0, 0)
def redraw(self): """ Request a redraw. If we're using XShape (optionally or forcibly) then render the image into the shape so that we only cut out clear sections """ self.needsredraw = False gdkwin = self.get_window() if self.piggyback_parent: self.piggyback_parent.redraw() return if not self.floating: (width, height) = self.get_size() self.width = width self.height = height if gdkwin: if not self.compositing or self.force_xshape: (width, height) = self.get_size() surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) surface_ctx = cairo.Context(surface) self.overlay_draw(None, surface_ctx) reg = Gdk.cairo_region_create_from_surface(surface) gdkwin.shape_combine_region(reg, 0, 0) else: gdkwin.shape_combine_region(None, 0, 0) self.queue_draw()
def test_region_to_py(self): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) context.paint() region = Gdk.cairo_region_create_from_surface(surface) r = region.get_extents() self.assertEqual((r.height, r.width), (10, 10))
def test_region_to_py(self): surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 10, 10) context = cairo.Context(surface) context.paint() region = Gdk.cairo_region_create_from_surface(surface) r = region.get_extents() self.assertEqual((r.height, r.width), (10, 10))
def set_untouchable(self): (w, h) = self.get_size() surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) surface_ctx = cairo.Context(surface) surface_ctx.set_source_rgba(0.0, 0.0, 0.0, 0.0) surface_ctx.set_operator(cairo.OPERATOR_SOURCE) surface_ctx.paint() reg = Gdk.cairo_region_create_from_surface(surface) self.input_shape_combine_region(reg)
def draw(self, widget, context): self.image = cairo.ImageSurface.create_from_png("claver-splash.png") input_region = Gdk.cairo_region_create_from_surface(self.image) self.input_shape_combine_region(input_region) context.set_operator(cairo.OPERATOR_SOURCE) context.set_source_surface(self.image, 0, 0) context.paint() context.set_operator(cairo.OPERATOR_OVER)
def set_untouchable(self): """ Create a custom input shape and tell it that all of the window is a cut-out This allows us to have a window above everything but that never gets clicked on """ (width, height) = self.get_size() surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) surface_ctx = cairo.Context(surface) surface_ctx.set_source_rgba(0.0, 0.0, 0.0, 0.0) surface_ctx.set_operator(cairo.OPERATOR_SOURCE) surface_ctx.paint() reg = Gdk.cairo_region_create_from_surface(surface) self.input_shape_combine_region(reg)
def redraw(self): gdkwin = self.get_window() if gdkwin: if not self.compositing or self.force_xshape: (w, h) = self.get_size() surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, w, h) surface_ctx = cairo.Context(surface) self.do_draw(surface_ctx) reg = Gdk.cairo_region_create_from_surface(surface) gdkwin.shape_combine_region(reg, 0, 0) else: gdkwin.shape_combine_region(None, 0, 0) self.queue_draw()
def createRegion(self, pixbuf): x = pixbuf.get_width() y = pixbuf.get_height() mask = cairo.ImageSurface(cairo.FORMAT_ARGB32, x, y) ctx = cairo.Context(mask) ctx.set_source_rgba(0.0, 0.0, 0.0, 0.0) ctx.rectangle(0, 0, x, y) ctx.fill() ctx.set_source_rgb(1.0, 1.0, 1.0) self.roundedrec(ctx, 0, 0, x, y, self.round, 1, False) ctx.close_path() ctx.fill_preserve() ctx.stroke() # デバッグ用 # mask.write_to_png('/tmp/mask.png') region = Gdk.cairo_region_create_from_surface(mask) return region
def updateWindowMask(self): surface = cairo.ImageSurface(cairo.Format.ARGB32, self.w, self.h) ctx = cairo.Context(surface) ctx.set_source_rgba(1.0, 1.0, 1.0, 0.0) ctx.set_operator(cairo.OPERATOR_CLEAR) ctx.paint() ctx.set_operator(cairo.OPERATOR_OVER) ctx.set_source_rgba(1.0, 1.0, 1.0) ctx.set_line_width(1) pix = 0 for y in range(0, self.h, 3): for x in range(0, self.w, 3): ctx.move_to(x, y) ctx.line_to(x + 2, y + 2) ctx.stroke() surface.write_to_png("temp.png") region = Gdk.cairo_region_create_from_surface(surface) self.mainWindow.shape_combine_region(region)
def draw_nav_button(self, widget, context): """ draws rectangles with rounded (circular arc) corners """ if widget.get_children()[0].get_text() == self.__activeButton: active = True else: active = False alloc = widget.get_allocation() width = alloc.width height = alloc.height buttonRadius = 20 xOffset = 0 yOffset = 0 # Create a surface to use as the input area for GtkEventBox surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) ctx = cairo.Context(surface) # Reset buffer background ctx.set_source_rgba(0.0, 0.0, 0.0, 0.0) # Transparent black ctx.rectangle(0, 0, width, height) ctx.fill() outline_top_left_offset = theme_prefs['OUTLINE'] / 2 outline_bottom_right_offset = theme_prefs['OUTLINE'] # Draw to the Cairo buffer self.draw_rounded_menu_button(context=ctx, x=outline_top_left_offset + xOffset, y=outline_top_left_offset + yOffset, width=width - outline_bottom_right_offset, height=height - outline_bottom_right_offset, radius=buttonRadius, lineWidth=theme_prefs['OUTLINE'], active=active) # Draw to the widget surface self.draw_rounded_menu_button(context=context, x=outline_top_left_offset + xOffset, y=outline_top_left_offset + yOffset, width=width - outline_bottom_right_offset, height=height - outline_bottom_right_offset, radius=buttonRadius, lineWidth=theme_prefs['OUTLINE'], active=active) # save file # surface.write_to_png("MyImage.png") input_region = Gdk.cairo_region_create_from_surface(surface) widget.input_shape_combine_region(input_region)
def cb_draw(self, widget, cr): cr.set_source_rgba(0.0, 0.0, 0.0, 0.0) cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.w, self.h) surface_ctx = cairo.Context(surface) surface_ctx.set_source_rgba(1.0, 1.0, 1.0, 0.0) surface_ctx.set_operator(cairo.OPERATOR_SOURCE) surface_ctx.paint() reg = Gdk.cairo_region_create_from_surface(surface) widget.input_shape_combine_region(reg) cr.move_to(0, 0) cr.set_source_rgba(1.0, 0.0, 0.0, 0.8) cr.set_line_width(2.0) # # Seriously? # The thing is, windows cannot overlap Panel or Launcher. # Ugly code taking care of this overlapping is below. # if self.y > self.panel_height - 1: cr.line_to(self.w, 0) else: cr.move_to(self.w, 0) if self.x + self.w < HW.screens[self.screen.get_number()]['width']: cr.line_to(self.w, self.h) else: cr.move_to(self.w, self.h) if self.y + self.h < HW.screens[self.screen.get_number()]['height']: cr.line_to(0, self.h) else: cr.move_to(0, self.h) if self.x > self.launcher_width: cr.line_to(0, 0) cr.stroke() cr.set_operator(cairo.OPERATOR_OVER)
def cb_draw(self, widget, cr): cr.set_source_rgba(0.0, 0.0, 0.0, 0.0) cr.set_operator(cairo.OPERATOR_SOURCE) cr.paint() surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.w, self.h) surface_ctx = cairo.Context(surface) surface_ctx.set_source_rgba(1.0, 1.0, 1.0, 0.0) surface_ctx.set_operator(cairo.OPERATOR_SOURCE) surface_ctx.paint() reg = Gdk.cairo_region_create_from_surface(surface) widget.input_shape_combine_region(reg) cr.move_to(0, 0) cr.set_source_rgba(1.0, 0.0, 0.0, 0.8) cr.set_line_width(2.0) # # Seriously? # The thing is, windows cannot overlap Panel or Launcher. # Ugly code taking care of this overlapping is below. # if self.y > self.panel_height - 1: cr.line_to(self.w, 0) else: cr.move_to(self.w, 0) if self.x + self.w < HW.screens[self.screen.get_number()]['width']: cr.line_to(self.w, self.h) else: cr.move_to(self.w, self.h) if self.y + self.h < HW.screens[self.screen.get_number()]['height']: cr.line_to(0, self.h) else: cr.move_to(0, self.h) if self.x > self.launcher_width: cr.line_to(0, 0) cr.stroke() cr.set_operator(cairo.OPERATOR_OVER)
def draw_cb(self, widget, cc): print("do_draw_cb") # Clear cairo context cc.set_source_rgba(0, 0, 0, 0) cc.set_operator(cairo.OPERATOR_SOURCE) cc.paint() # Scale the context so that the cover image area is 1 x 1 rect = self.get_allocation() if self.conf['draw_reflection']: cover_area_size = min(rect.width - self.conf['blur']/2, (rect.height - self.conf['blur']/2) / (1 + self.conf['reflection_height'])) else: cover_area_size = min(rect.width - self.conf['blur']/2, (rect.height - self.conf['blur']/2)) if self.conf['text_position'] in [POSITION_SW, POSITION_NW]: x_trans = int(round(rect.width - cover_area_size - self.conf['blur']/2)) else: x_trans = int(round(self.conf['blur']/2)) cc.translate(x_trans, 0) cc.scale(cover_area_size, cover_area_size) cc.push_group() self.song_info.draw(cc) if self.mouse_over: self.desktop_buttons.draw(cc) cc.save() cc.translate((1 - self.conf['hover_size']) / 2, self.conf['border']) cc.scale(self.conf['hover_size'], self.conf['hover_size']) if (self.conf['text_position'] in [POSITION_NW, POSITION_NE]) and (not self.mouse_over): if(self.cover_image.w > self.cover_image.h): cc.save() cc.translate(0, (self.cover_image.h - self.cover_image.w) / self.cover_image.w) self.cover_image.draw(cc, cover_area_size) if (self.conf['text_position'] in [POSITION_NW, POSITION_NE]) and (not self.mouse_over): if(self.cover_image.w > self.cover_image.h): cc.restore() if self.mouse_over: cc.restore() graphics = cc.pop_group() # Draw main graphics cc.set_source(graphics) cc.set_operator(cairo.OPERATOR_OVER) cc.paint() # Draw reflections if self.conf['draw_reflection']: cc.save() cc.set_operator(cairo.OPERATOR_ADD) cc.translate(0, 2.02) if (self.conf['text_position'] in [POSITION_NW, POSITION_NE]) and (not self.mouse_over): if(self.cover_image.w > self.cover_image.h): cc.save() cc.translate(0, 2 * (self.cover_image.h - self.cover_image.w) / self.cover_image.w) cc.scale(1, -1) cc.push_group() x_scale = cc.get_matrix()[0] r1 = int(self.conf['blur'] / 2 + 1.5) r0 = r1 - self.conf['blur'] - 1 bn = (self.conf['blur'] + 1)**2 for dx in range(r0, r1): for dy in range(r0, r1): cc.save() cc.translate(dx/x_scale, dy/x_scale) cc.set_source(graphics) cc.paint_with_alpha(1/bn) cc.restore() graphics = cc.pop_group() cc.set_source(graphics) shadow_mask = cairo.LinearGradient(0, 1 - self.conf['reflection_height'], 0, 1) shadow_mask.add_color_stop_rgba(0, 0, 0, 0, 0) shadow_mask.add_color_stop_rgba(1, 0, 0, 0, self.conf['reflection_intensity']) cc.mask(shadow_mask) if (self.conf['text_position'] in [POSITION_NW, POSITION_NE]) and (not self.mouse_over): if(self.cover_image.w > self.cover_image.h): cc.restore() cc.restore() # Input mask, only the cover image is clickable # Will, (and should) only work if parent is Gtk.Window surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(rect.width), int(rect.height)) ccmask = cairo.Context(surface) roundedrec(ccmask, int(x_trans), 0, cover_area_size, cover_area_size, self.conf['roundness']) ccmask.fill() # bug in python-cairo, upstream is patched, but only for python3-cairo # https://bugs.launchpad.net/ubuntu/+source/pygobject/+bug/1028115 # https://bugzilla.gnome.org/show_bug.cgi?id=667959 # https://bugs.freedesktop.org/show_bug.cgi?id=44336 # for the moment wrap this into a try except so that it fails gracefully # need to test this on a distro patched and only running python3-cairo #21/04/14 - crash observed on 14.04 - currently presume this is a bug so #lets work around this by a test with the pygobject-version 3.12 try: print (desktop_rb3compat.pygobject_version()) if desktop_rb3compat.pygobject_version() < 3.12: region = Gdk.cairo_region_create_from_surface(surface) self.get_parent().input_shape_combine_region(region) except: pass # Draw border if self.draw_border: print("drawborder") cc.identity_matrix() cc.rectangle(0, 0, rect.width, rect.height) cc.set_line_width(2) cc.set_source_rgba(1, 1, 1, 0.35) cc.set_dash([10,10], 0) cc.stroke_preserve() cc.set_source_rgba(0, 0, 0, 0.35) cc.set_dash([10,10], 10) cc.stroke()
def draw_cb(self, widget, cc): print("do_draw_cb") # Clear cairo context cc.set_source_rgba(0, 0, 0, 0) cc.set_operator(cairo.OPERATOR_SOURCE) cc.paint() # Scale the context so that the cover image area is 1 x 1 rect = self.get_allocation() if self.conf['draw_reflection']: cover_area_size = min(rect.width - self.conf['blur']/2, (rect.height - self.conf['blur']/2) / (1 + self.conf['reflection_height'])) else: cover_area_size = min(rect.width - self.conf['blur']/2, (rect.height - self.conf['blur']/2)) if self.conf['text_position'] in [POSITION_SW, POSITION_NW]: x_trans = int(round(rect.width - cover_area_size - self.conf['blur']/2)) else: x_trans = int(round(self.conf['blur']/2)) cc.translate(x_trans, 0) cc.scale(cover_area_size, cover_area_size) cc.push_group() self.song_info.draw(cc) if self.mouse_over: self.desktop_buttons.draw(cc) cc.save() cc.translate((1 - self.conf['hover_size']) / 2, self.conf['border']) cc.scale(self.conf['hover_size'], self.conf['hover_size']) if (self.conf['text_position'] in [POSITION_NW, POSITION_NE]) and (not self.mouse_over): if(self.cover_image.w > self.cover_image.h): cc.save() cc.translate(0, (self.cover_image.h - self.cover_image.w) / self.cover_image.w) self.cover_image.draw(cc, cover_area_size) if (self.conf['text_position'] in [POSITION_NW, POSITION_NE]) and (not self.mouse_over): if(self.cover_image.w > self.cover_image.h): cc.restore() if self.mouse_over: cc.restore() graphics = cc.pop_group() # Draw main graphics cc.set_source(graphics) cc.set_operator(cairo.OPERATOR_OVER) cc.paint() # Draw reflections if self.conf['draw_reflection']: cc.save() cc.set_operator(cairo.OPERATOR_ADD) cc.translate(0, 2.02) if (self.conf['text_position'] in [POSITION_NW, POSITION_NE]) and (not self.mouse_over): if(self.cover_image.w > self.cover_image.h): cc.save() cc.translate(0, 2 * (self.cover_image.h - self.cover_image.w) / self.cover_image.w) cc.scale(1, -1) cc.push_group() x_scale = cc.get_matrix()[0] r1 = int(self.conf['blur'] / 2 + 1.5) r0 = r1 - self.conf['blur'] - 1 bn = (self.conf['blur'] + 1)**2 for dx in range(r0, r1): for dy in range(r0, r1): cc.save() cc.translate(dx/x_scale, dy/x_scale) cc.set_source(graphics) cc.paint_with_alpha(1/bn) cc.restore() graphics = cc.pop_group() cc.set_source(graphics) shadow_mask = cairo.LinearGradient(0, 1 - self.conf['reflection_height'], 0, 1) shadow_mask.add_color_stop_rgba(0, 0, 0, 0, 0) shadow_mask.add_color_stop_rgba(1, 0, 0, 0, self.conf['reflection_intensity']) cc.mask(shadow_mask) if (self.conf['text_position'] in [POSITION_NW, POSITION_NE]) and (not self.mouse_over): if(self.cover_image.w > self.cover_image.h): cc.restore() cc.restore() # Input mask, only the cover image is clickable # Will, (and should) only work if parent is Gtk.Window surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(rect.width), int(rect.height)) ccmask = cairo.Context(surface) roundedrec(ccmask, int(x_trans), 0, cover_area_size, cover_area_size, self.conf['roundness']) ccmask.fill() # bug in python-cairo, upstream is patched, but only for python3-cairo # https://bugs.launchpad.net/ubuntu/+source/pygobject/+bug/1028115 # https://bugzilla.gnome.org/show_bug.cgi?id=667959 # https://bugs.freedesktop.org/show_bug.cgi?id=44336 # for the moment wrap this into a try except so that it fails gracefully # need to test this on a distro patched and only running python3-cairo #21/04/14 - crash observed on 14.04 - currently presume this is a bug so #lets work around this by a test with the pygobject-version 3.12 try: print (desktop_rb3compat.pygobject_version()) if desktop_rb3compat.pygobject_version() < 3.12: region = Gdk.cairo_region_create_from_surface(surface) self.get_parent().input_shape_combine_region(region) except: pass # Draw border if self.draw_border: print("drawborder") cc.identity_matrix() cc.rectangle(0, 0, rect.width, rect.height) cc.set_line_width(2) cc.set_source_rgba(1, 1, 1, 0.35) cc.set_dash([10,10], 0) cc.stroke_preserve() cc.set_source_rgba(0, 0, 0, 0.35) cc.set_dash([10,10], 10) cc.stroke()