def _draw_handle_shadow(self, context, alpha_factor): rect = self.get_rect() context.save() # There is a massive performance boost for groups when clipping is used. # Integer limits are again dramatically faster (x4) then using floats. # for 1000x draw_drop_shadow: # with clipping: ~300ms, without: ~11000ms context.rectangle(*self.get_shadow_rect().int()) context.clip() context.push_group() # draw the shadow context.push_group_with_content(cairo.CONTENT_ALPHA) self._build_handle_path(context) context.set_source_rgba(0.0, 0.0, 0.0, 1.0) context.fill() group = context.pop_group() drop_shadow(context, group, rect, self._shadow_size, self._shadow_offset, self._shadow_alpha, 5) # cut out the handle area, because the handle is transparent context.save() context.set_operator(cairo.OPERATOR_CLEAR) context.set_source_rgba(0.0, 0.0, 0.0, 1.0) self._build_handle_path(context) context.fill() context.restore() context.pop_group_to_source() context.paint() context.restore()
def create_shadow_surface(self, base_context, shadow_steps, shadow_alpha): """ Draw shadow and shaded halo. Somewhat slow, make sure to cache the result. Glitchy, if the clip-rect covers only a single button (Precise), therefore, draw only with unrestricted clipping rect. """ rect = self.get_canvas_rect() root = self.get_layout_root() if rect.is_empty(): return None extent = min(root.context.scale_log_to_canvas((1.0, 1.0))) alpha = pi / 2 + self.get_light_direction() shadow_opacity = config.theme_settings.key_shadow_strength * \ shadow_alpha shadow_scale = config.theme_settings.key_shadow_size / 20.0 shadow_radius = max(extent * shadow_scale, 1.0) shadow_displacement = max(extent * shadow_scale * 0.26, 1.0) shadow_offset = (shadow_displacement * cos(alpha), shadow_displacement * sin(alpha)) has_halo = shadow_steps > 1 and not config.window.transparent_background halo_opacity = shadow_opacity * 0.11 halo_radius = max(extent * 8.0, 1.0) clip_rect = rect.offset(shadow_offset[0]+1, shadow_offset[1]+1) if has_halo: clip_rect = clip_rect.inflate(halo_radius * 1.5) else: clip_rect = clip_rect.inflate(shadow_radius * 1.3) clip_rect = clip_rect.int() # create caching surface target = base_context.get_target() surface = target.create_similar(cairo.CONTENT_ALPHA, clip_rect.w, clip_rect.h) context = cairo.Context(surface) # paint the surface context.save() context.translate(-clip_rect.x, -clip_rect.y) context.rectangle(*clip_rect) context.clip() context.push_group_with_content(cairo.CONTENT_ALPHA) self._build_canvas_path(context, rect) context.set_source_rgba(0.0, 0.0, 0.0, 1.0) context.fill() shape = context.pop_group() # shadow drop_shadow(context, shape, rect, shadow_radius, shadow_offset, shadow_opacity, shadow_steps) # halo if has_halo: drop_shadow(context, shape, rect, halo_radius, shadow_offset, halo_opacity, shadow_steps) # cut out the key area, the key may be transparent context.set_operator(cairo.OPERATOR_CLEAR) context.set_source_rgba(0.0, 0.0, 0.0, 1.0) self._build_canvas_path(context, rect) context.fill() context.restore() return surface, clip_rect
def create_shadow_surface(self, base_context, shadow_steps, shadow_alpha): """ Draw shadow and shaded halo. Somewhat slow, make sure to cache the result. Glitchy, if the clip-rect covers only a single button (Precise), therefore, draw only with unrestricted clipping rect. """ rect = self.get_canvas_rect() root = self.get_layout_root() if rect.is_empty(): return None extent = min(root.context.scale_log_to_canvas((1.0, 1.0))) alpha = pi / 2 + self.get_light_direction() shadow_opacity = config.theme_settings.key_shadow_strength * \ shadow_alpha shadow_scale = config.theme_settings.key_shadow_size / 20.0 shadow_radius = max(extent * shadow_scale, 1.0) shadow_displacement = max(extent * shadow_scale * 0.26, 1.0) shadow_offset = (shadow_displacement * cos(alpha), shadow_displacement * sin(alpha)) has_halo = shadow_steps > 1 and not config.window.transparent_background halo_opacity = shadow_opacity * 0.11 halo_radius = max(extent * 8.0, 1.0) clip_rect = rect.offset(shadow_offset[0] + 1, shadow_offset[1] + 1) if has_halo: clip_rect = clip_rect.inflate(halo_radius * 1.5) else: clip_rect = clip_rect.inflate(shadow_radius * 1.3) clip_rect = clip_rect.int() # create caching surface target = base_context.get_target() surface = target.create_similar(cairo.CONTENT_ALPHA, clip_rect.w, clip_rect.h) context = cairo.Context(surface) surface.set_device_offset(-clip_rect.x, -clip_rect.y) # paint the surface context.save() context.rectangle(*clip_rect) context.clip() context.push_group_with_content(cairo.CONTENT_ALPHA) self.build_rect_path(context, rect) context.set_source_rgba(0.0, 0.0, 0.0, 1.0) context.fill() shape = context.pop_group() # shadow drop_shadow(context, shape, rect, shadow_radius, shadow_offset, shadow_opacity, shadow_steps) # halo if has_halo: drop_shadow(context, shape, rect, halo_radius, shadow_offset, halo_opacity, shadow_steps) # cut out the key area, the key may be transparent context.set_operator(cairo.OPERATOR_CLEAR) context.set_source_rgba(0.0, 0.0, 0.0, 1.0) self.build_rect_path(context, rect) context.fill() context.restore() return surface