def _draw_transparent_background(self, context, lod): """ fill with the transparent background color """ corner_radius = config.CORNER_RADIUS rect = self.get_keyboard_frame_rect() fill = self.get_background_rgba() fill_gradient = config.theme_settings.background_gradient if lod == LOD.MINIMAL or \ fill_gradient == 0: context.set_source_rgba(*fill) else: fill_gradient /= 100.0 direction = config.theme_settings.key_gradient_direction alpha = -pi/2.0 + pi * direction / 180.0 gline = gradient_line(rect, alpha) pat = cairo.LinearGradient (*gline) rgba = brighten(+fill_gradient*.5, *fill) pat.add_color_stop_rgba(0, *rgba) rgba = brighten(-fill_gradient*.5, *fill) pat.add_color_stop_rgba(1, *rgba) context.set_source (pat) frame = self.can_draw_frame() if frame: roundrect_arc(context, rect, corner_radius) else: context.rectangle(*rect) context.fill() if frame: self.draw_window_frame(context, lod) self.draw_keyboard_frame(context, lod)
def _draw_transparent_background(self, context, lod): """ fill with the transparent background color """ corner_radius = config.CORNER_RADIUS rect = self.get_keyboard_frame_rect() fill = self.get_background_rgba() fill_gradient = config.theme_settings.background_gradient if lod == LOD.MINIMAL or \ fill_gradient == 0: context.set_source_rgba(*fill) else: fill_gradient /= 100.0 direction = config.theme_settings.key_gradient_direction alpha = -pi / 2.0 + pi * direction / 180.0 gline = gradient_line(rect, alpha) pat = cairo.LinearGradient(*gline) rgba = brighten(+fill_gradient * .5, *fill) pat.add_color_stop_rgba(0, *rgba) rgba = brighten(-fill_gradient * .5, *fill) pat.add_color_stop_rgba(1, *rgba) context.set_source(pat) frame = self.can_draw_frame() if frame: roundrect_arc(context, rect, corner_radius) else: context.rectangle(*rect) context.fill() if frame: self.draw_window_frame(context, lod) self.draw_keyboard_frame(context, lod)
def draw_gradient_key(self, cr, fill, line_width, lod): # simple gradients for fill and stroke fill_gradient = config.theme_settings.key_fill_gradient / 100.0 stroke_gradient = self.get_stroke_gradient() alpha = self.get_gradient_angle() rect = self.get_canvas_rect() self._build_canvas_path(cr, rect) gline = gradient_line(rect, alpha) # fill if self.show_face: if fill_gradient and lod: pat = cairo.LinearGradient (*gline) rgba = brighten(+fill_gradient*.5, *fill) pat.add_color_stop_rgba(0, *rgba) rgba = brighten(-fill_gradient*.5, *fill) pat.add_color_stop_rgba(1, *rgba) cr.set_source (pat) else: # take gradient from color scheme (not implemented) cr.set_source_rgba(*fill) if self.show_border: cr.fill_preserve() else: cr.fill() # stroke if self.show_border: if stroke_gradient: if lod: stroke = fill pat = cairo.LinearGradient (*gline) rgba = brighten(+stroke_gradient*.5, *stroke) pat.add_color_stop_rgba(0, *rgba) rgba = brighten(-stroke_gradient*.5, *stroke) pat.add_color_stop_rgba(1, *rgba) cr.set_source (pat) else: cr.set_source_rgba(*fill) else: cr.set_source_rgba(*self.get_stroke_color()) cr.set_line_width(line_width) cr.stroke()
def draw_gradient_key(self, cr, fill, line_width, lod): # simple gradients for fill and stroke fill_gradient = config.theme_settings.key_fill_gradient / 100.0 stroke_gradient = self.get_stroke_gradient() alpha = self.get_gradient_angle() rect = self.get_canvas_rect() self._build_canvas_path(cr, rect) gline = gradient_line(rect, alpha) # fill if self.show_face: if fill_gradient and lod: pat = cairo.LinearGradient(*gline) rgba = brighten(+fill_gradient * .5, *fill) pat.add_color_stop_rgba(0, *rgba) rgba = brighten(-fill_gradient * .5, *fill) pat.add_color_stop_rgba(1, *rgba) cr.set_source(pat) else: # take gradient from color scheme (not implemented) cr.set_source_rgba(*fill) if self.show_border: cr.fill_preserve() else: cr.fill() # stroke if self.show_border: if stroke_gradient: if lod: stroke = fill pat = cairo.LinearGradient(*gline) rgba = brighten(+stroke_gradient * .5, *stroke) pat.add_color_stop_rgba(0, *rgba) rgba = brighten(-stroke_gradient * .5, *stroke) pat.add_color_stop_rgba(1, *rgba) cr.set_source(pat) else: cr.set_source_rgba(*fill) else: cr.set_source_rgba(*self.get_stroke_color()) cr.set_line_width(line_width) cr.stroke()
def draw_dish_key(self, cr, fill, line_width, lod): canvas_rect = self.get_canvas_rect() if self.geometry: geometry = self.geometry else: geometry = KeyGeometry.from_rect(self.get_border_rect()) size_scale_x, size_scale_y = geometry.scale_log_to_size((1.0, 1.0)) # compensate for smaller size due to missing stroke canvas_rect = canvas_rect.inflate(1.0) # parameters for the base path base_rgba = brighten(-0.200, *fill) stroke_gradient = self.get_stroke_gradient() light_dir = self.get_light_direction() - pi * 0.5 # 0 = light from top lightx = cos(light_dir) lighty = sin(light_dir) key_offset_x, key_offset_y, key_size_x, key_size_y = \ self.get_key_offset_size(geometry) radius_pct = max(config.theme_settings.roundrect_radius, 2) radius_pct = max(radius_pct, 2) # too much +-1 fudging for square corners chamfer_size = self.get_chamfer_size() chamfer_size = (self.context.scale_log_to_canvas_x(chamfer_size) + self.context.scale_log_to_canvas_y(chamfer_size)) * 0.5 # parameters for the top path, key face stroke_width = self.get_stroke_width() key_offset_top_y = key_offset_y - \ config.DISH_KEY_Y_OFFSET * stroke_width border = config.DISH_KEY_BORDER scale_top_x = 1.0 - (border[0] * stroke_width * size_scale_x * 2.0) scale_top_y = 1.0 - (border[1] * stroke_width * size_scale_y * 2.0) key_size_top_x = key_size_x * scale_top_x key_size_top_y = key_size_y * scale_top_y chamfer_size_top = chamfer_size * (scale_top_x + scale_top_y) * 0.5 # realize all paths we're going to use polygons, polygon_paths = \ self.get_canvas_polygons(geometry, key_offset_x, key_offset_y, key_size_x, key_size_y, radius_pct, chamfer_size) polygons_top, polygon_paths_top = \ self.get_canvas_polygons(geometry, key_offset_x, key_offset_top_y, key_size_top_x - size_scale_x, key_size_top_y - size_scale_y, radius_pct, chamfer_size_top) polygons_top1, polygon_paths_top1 = \ self.get_canvas_polygons(geometry, key_offset_x, key_offset_top_y, key_size_top_x, key_size_top_y, radius_pct, chamfer_size_top) # draw key border if self.show_border: if not lod: cr.set_source_rgba(*base_rgba) for path in polygon_paths: rounded_polygon_path_to_cairo_path(cr, path) cr.fill() else: for ipg, polygon in enumerate(polygons): polygon_top = polygons_top[ipg] path = polygon_paths[ipg] path_top = polygon_paths_top[ipg] self._draw_dish_key_border(cr, path, path_top, polygon, polygon_top, base_rgba, stroke_gradient, lightx, lighty) # Draw the key face, the smaller top rectangle. if self.show_face: if not lod: cr.set_source_rgba(*fill) else: # Simulate the concave key dish with a gradient that has # a sligthly brighter middle section. if self.id == "SPCE": angle = pi / 2.0 # space has a convex top else: angle = 0.0 # all others are concave fill_gradient = config.theme_settings.key_fill_gradient / 100.0 dark_rgba = brighten(-fill_gradient*.5, *fill) bright_rgba = brighten(+fill_gradient*.5, *fill) gline = gradient_line(canvas_rect, angle) pat = cairo.LinearGradient (*gline) pat.add_color_stop_rgba(0.0, *dark_rgba) pat.add_color_stop_rgba(0.5, *bright_rgba) pat.add_color_stop_rgba(1.0, *dark_rgba) cr.set_source (pat) for path in polygon_paths_top1: rounded_polygon_path_to_cairo_path(cr, path) cr.fill()
def draw_dish_key(self, context, rect, fill, line_width, lod): # compensate for smaller size due to missing stroke rect = rect.inflate(1.0) # parameters for the base rectangle w, h = rect.get_size() w2, h2 = w * 0.5, h * 0.5 xc, yc = rect.get_center() radius_pct = config.theme_settings.roundrect_radius radius_pct = max(radius_pct, 2) # too much +-1 fudging for square corners r, k = self.get_curved_rect_params(rect, radius_pct) base_rgba = brighten(-0.200, *fill) stroke_gradient = config.theme_settings.key_stroke_gradient / 100.0 light_dir = self.get_light_direction() # parameters for the top rectangle, key face scale = config.theme_settings.key_stroke_width / 100.0 border = config.DISH_KEY_BORDER border = (border[0] * scale, border[1] * scale) border = self.context.scale_log_to_canvas(border) offset_top = self.context.scale_log_to_canvas_y( config.DISH_KEY_Y_OFFSET) rect_top = rect.deflate(*border).offset(0, -offset_top) rect_top.w = max(rect_top.w, 0.0) rect_top.h = max(rect_top.h, 0.0) top_radius_scale = rect_top.h / float(rect.h) r_top, k_top = self.get_curved_rect_params( rect_top, radius_pct * top_radius_scale) # draw key border if self.show_border: if not lod: self.build_rect_path(context, rect) context.set_source_rgba(*base_rgba) context.fill() else: # lambert lighting edge_colors = [] for edge in range(4): normal_dir = edge * pi / 2.0 # 0 = light from top I = cos(normal_dir - light_dir) * stroke_gradient * 0.8 edge_colors.append(brighten(I, *base_rgba)) context.save() context.translate(xc, yc) # edge sections, edge 0 = top for edge in range(4): if edge & 1: p = (h2, w2) p_top = [rect_top.h / 2.0, rect_top.w / 2.0] else: p = (w2, h2) p_top = [rect_top.w / 2.0, rect_top.h / 2.0] m = cairo.Matrix() m.rotate(edge * pi / 2.0) p0 = m.transform_point(-p[0] + r - 1, -p[1]) # -1 to fill gaps p1 = m.transform_point(p[0] - r + 1, -p[1]) p0_top = m.transform_point(p_top[0] - r_top + 1, -p_top[1] + 1) p1_top = m.transform_point(-p_top[0] + r_top - 1, -p_top[1] + 1) p0_top = (p0_top[0], p0_top[1] - offset_top) p1_top = (p1_top[0], p1_top[1] - offset_top) context.set_source_rgba(*edge_colors[edge]) context.move_to(p0[0], p0[1]) context.line_to(p1[0], p1[1]) context.line_to(*p0_top) context.line_to(*p1_top) context.close_path() context.fill() # corner sections for edge in range(4): if edge & 1: p = (h2, w2) p_top = [rect_top.h / 2.0, rect_top.w / 2.0] else: p = (w2, h2) p_top = [rect_top.w / 2.0, rect_top.h / 2.0] m = cairo.Matrix() m.rotate(edge * pi / 2.0) p1 = m.transform_point(p[0] - r, -p[1]) p2 = m.transform_point(p[0], -p[1] + r) pk0 = m.transform_point(p[0] - k, -p[1]) pk1 = m.transform_point(p[0], -p[1] + k) p0_top = m.transform_point(p_top[0] - r_top, -p_top[1]) p2_top = m.transform_point(p_top[0], -p_top[1] + r_top) p0_top = (p0_top[0], p0_top[1] - offset_top) p2_top = (p2_top[0], p2_top[1] - offset_top) # Fake Gouraud shading: draw a gradient between mid points # of the lines connecting the base with the top rectangle. gline = ((p1[0] + p0_top[0]) / 2.0, (p1[1] + p0_top[1]) / 2.0, (p2[0] + p2_top[0]) / 2.0, (p2[1] + p2_top[1]) / 2.0) pat = cairo.LinearGradient(*gline) pat.add_color_stop_rgba(0.0, *edge_colors[edge]) pat.add_color_stop_rgba(1.0, *edge_colors[(edge + 1) % 4]) context.set_source(pat) context.move_to(*p1) context.curve_to(pk0[0], pk0[1], pk1[0], pk1[1], p2[0], p2[1]) context.line_to(*p2_top) context.line_to(*p0_top) context.close_path() context.fill() context.restore() # Draw the key face, the smaller top rectangle. if self.show_face: if not lod: context.set_source_rgba(*fill) else: # Simulate the concave key dish with a gradient that has # a sligthly brighter middle section. if self.id == "SPCE": angle = pi / 2.0 # space has a convex top else: angle = 0.0 # all others are concave fill_gradient = config.theme_settings.key_fill_gradient / 100.0 dark_rgba = brighten(-fill_gradient * .5, *fill) bright_rgba = brighten(+fill_gradient * .5, *fill) gline = gradient_line(rect, angle) pat = cairo.LinearGradient(*gline) pat.add_color_stop_rgba(0.0, *dark_rgba) pat.add_color_stop_rgba(0.5, *bright_rgba) pat.add_color_stop_rgba(1.0, *dark_rgba) context.set_source(pat) self.build_rect_path(context, rect_top, top_radius_scale) context.fill()
def draw_dish_key(self, cr, fill, line_width, lod): canvas_rect = self.get_canvas_rect() if self.geometry: geometry = self.geometry else: geometry = KeyGeometry.from_rect(self.get_border_rect()) size_scale_x, size_scale_y = geometry.scale_log_to_size((1.0, 1.0)) # compensate for smaller size due to missing stroke canvas_rect = canvas_rect.inflate(1.0) # parameters for the base path base_rgba = brighten(-0.200, *fill) stroke_gradient = self.get_stroke_gradient() light_dir = self.get_light_direction() - pi * 0.5 # 0 = light from top lightx = cos(light_dir) lighty = sin(light_dir) key_offset_x, key_offset_y, key_size_x, key_size_y = \ self.get_key_offset_size(geometry) radius_pct = max(config.theme_settings.roundrect_radius, 2) radius_pct = max(radius_pct, 2) # too much +-1 fudging for square corners chamfer_size = self.get_chamfer_size() chamfer_size = (self.context.scale_log_to_canvas_x(chamfer_size) + self.context.scale_log_to_canvas_y(chamfer_size)) * 0.5 # parameters for the top path, key face stroke_width = self.get_stroke_width() key_offset_top_y = key_offset_y - \ config.DISH_KEY_Y_OFFSET * stroke_width border = config.DISH_KEY_BORDER scale_top_x = 1.0 - (border[0] * stroke_width * size_scale_x * 2.0) scale_top_y = 1.0 - (border[1] * stroke_width * size_scale_y * 2.0) key_size_top_x = key_size_x * scale_top_x key_size_top_y = key_size_y * scale_top_y chamfer_size_top = chamfer_size * (scale_top_x + scale_top_y) * 0.5 # realize all paths we're going to use polygons, polygon_paths = \ self.get_canvas_polygons(geometry, key_offset_x, key_offset_y, key_size_x, key_size_y, radius_pct, chamfer_size) polygons_top, polygon_paths_top = \ self.get_canvas_polygons(geometry, key_offset_x, key_offset_top_y, key_size_top_x - size_scale_x, key_size_top_y - size_scale_y, radius_pct, chamfer_size_top) polygons_top1, polygon_paths_top1 = \ self.get_canvas_polygons(geometry, key_offset_x, key_offset_top_y, key_size_top_x, key_size_top_y, radius_pct, chamfer_size_top) # draw key border if self.show_border: if not lod: cr.set_source_rgba(*base_rgba) for path in polygon_paths: rounded_polygon_path_to_cairo_path(cr, path) cr.fill() else: for ipg, polygon in enumerate(polygons): polygon_top = polygons_top[ipg] path = polygon_paths[ipg] path_top = polygon_paths_top[ipg] self._draw_dish_key_border(cr, path, path_top, polygon, polygon_top, base_rgba, stroke_gradient, lightx, lighty) # Draw the key face, the smaller top rectangle. if self.show_face: if not lod: cr.set_source_rgba(*fill) else: # Simulate the concave key dish with a gradient that has # a sligthly brighter middle section. if self.id == "SPCE": angle = pi / 2.0 # space has a convex top else: angle = 0.0 # all others are concave fill_gradient = config.theme_settings.key_fill_gradient / 100.0 dark_rgba = brighten(-fill_gradient * .5, *fill) bright_rgba = brighten(+fill_gradient * .5, *fill) gline = gradient_line(canvas_rect, angle) pat = cairo.LinearGradient(*gline) pat.add_color_stop_rgba(0.0, *dark_rgba) pat.add_color_stop_rgba(0.5, *bright_rgba) pat.add_color_stop_rgba(1.0, *dark_rgba) cr.set_source(pat) for path in polygon_paths_top1: rounded_polygon_path_to_cairo_path(cr, path) cr.fill()
def draw_dish_key(self, context, rect, fill, line_width, lod): # compensate for smaller size due to missing stroke rect = rect.inflate(1.0) # parameters for the base rectangle w, h = rect.get_size() w2, h2 = w * 0.5, h * 0.5 xc, yc = rect.get_center() radius_pct = config.theme_settings.roundrect_radius radius_pct = max(radius_pct, 2) # too much +-1 fudging for square corners r, k = self.get_curved_rect_params(rect, radius_pct) base_rgba = brighten(-0.200, *fill) stroke_gradient = config.theme_settings.key_stroke_gradient / 100.0 light_dir = self.get_light_direction() # parameters for the top rectangle, key face scale = config.theme_settings.key_stroke_width / 100.0 border = config.DISH_KEY_BORDER border = (border[0] * scale, border[1] * scale) border = self.context.scale_log_to_canvas(border) offset_top = self.context.scale_log_to_canvas_y(config.DISH_KEY_Y_OFFSET) rect_top = rect.deflate(*border).offset(0, -offset_top) rect_top.w = max(rect_top.w, 0.0) rect_top.h = max(rect_top.h, 0.0) top_radius_scale = rect_top.h / float(rect.h) r_top, k_top = self.get_curved_rect_params(rect_top, radius_pct * top_radius_scale) # draw key border if self.show_border: if not lod: self.build_rect_path(context, rect) context.set_source_rgba(*base_rgba) context.fill() else: # lambert lighting edge_colors = [] for edge in range(4): normal_dir = edge * pi / 2.0 # 0 = light from top I = cos(normal_dir - light_dir) * stroke_gradient * 0.8 edge_colors.append(brighten(I, *base_rgba)) context.save() context.translate(xc, yc) # edge sections, edge 0 = top for edge in range(4): if edge & 1: p = (h2, w2) p_top = [rect_top.h / 2.0, rect_top.w / 2.0] else: p = (w2, h2) p_top = [rect_top.w / 2.0, rect_top.h / 2.0] m = cairo.Matrix() m.rotate(edge * pi / 2.0) p0 = m.transform_point(-p[0] + r - 1, -p[1]) # -1 to fill gaps p1 = m.transform_point(p[0] - r + 1, -p[1]) p0_top = m.transform_point(p_top[0] - r_top + 1, -p_top[1] + 1) p1_top = m.transform_point(-p_top[0] + r_top - 1, -p_top[1] + 1) p0_top = (p0_top[0], p0_top[1] - offset_top) p1_top = (p1_top[0], p1_top[1] - offset_top) context.set_source_rgba(*edge_colors[edge]) context.move_to(p0[0], p0[1]) context.line_to(p1[0], p1[1]) context.line_to(*p0_top) context.line_to(*p1_top) context.close_path() context.fill() # corner sections for edge in range(4): if edge & 1: p = (h2, w2) p_top = [rect_top.h / 2.0, rect_top.w / 2.0] else: p = (w2, h2) p_top = [rect_top.w / 2.0, rect_top.h / 2.0] m = cairo.Matrix() m.rotate(edge * pi / 2.0) p1 = m.transform_point(p[0] - r, -p[1]) p2 = m.transform_point(p[0], -p[1] + r) pk0 = m.transform_point(p[0] - k, -p[1]) pk1 = m.transform_point(p[0], -p[1] + k) p0_top = m.transform_point(p_top[0] - r_top, -p_top[1]) p2_top = m.transform_point(p_top[0], -p_top[1] + r_top) p0_top = (p0_top[0], p0_top[1] - offset_top) p2_top = (p2_top[0], p2_top[1] - offset_top) # Fake Gouraud shading: draw a gradient between mid points # of the lines connecting the base with the top rectangle. gline = ( (p1[0] + p0_top[0]) / 2.0, (p1[1] + p0_top[1]) / 2.0, (p2[0] + p2_top[0]) / 2.0, (p2[1] + p2_top[1]) / 2.0, ) pat = cairo.LinearGradient(*gline) pat.add_color_stop_rgba(0.0, *edge_colors[edge]) pat.add_color_stop_rgba(1.0, *edge_colors[(edge + 1) % 4]) context.set_source(pat) context.move_to(*p1) context.curve_to(pk0[0], pk0[1], pk1[0], pk1[1], p2[0], p2[1]) context.line_to(*p2_top) context.line_to(*p0_top) context.close_path() context.fill() context.restore() # Draw the key face, the smaller top rectangle. if self.show_face: if not lod: context.set_source_rgba(*fill) else: # Simulate the concave key dish with a gradient that has # a sligthly brighter middle section. if self.id == "SPCE": angle = pi / 2.0 # space has a convex top else: angle = 0.0 # all others are concave fill_gradient = config.theme_settings.key_fill_gradient / 100.0 dark_rgba = brighten(-fill_gradient * 0.5, *fill) bright_rgba = brighten(+fill_gradient * 0.5, *fill) gline = gradient_line(rect, angle) pat = cairo.LinearGradient(*gline) pat.add_color_stop_rgba(0.0, *dark_rgba) pat.add_color_stop_rgba(0.5, *bright_rgba) pat.add_color_stop_rgba(1.0, *dark_rgba) context.set_source(pat) self.build_rect_path(context, rect_top, top_radius_scale) context.fill()