static gboolean cb_draw(GtkWidget *wid, cairo_t *cr, gSeparator *data) { gint x, y, w, h; gColor color; x = y = 0; w = data->width(); h = data->height(); if (w == 1 || h == 1) { color = data->foreground(); if (color == COLOR_DEFAULT) color = gDesktop::lightfgColor(); gt_cairo_set_source_color(cr, color); cairo_rectangle(cr, x, y, w, h); cairo_fill(cr); } else if (w>=h) gtk_render_line(gtk_widget_get_style_context(wid), cr, x, y + (h / 2), x + w - 1, y + (h / 2)); else gtk_render_line(gtk_widget_get_style_context(wid), cr, x + (w / 2), y, x + (w / 2), y + h - 1); return false; }
static gboolean lyric_show_viewport_draw(GtkWidget *widget,cairo_t *cr) { LyricShowViewport *lsv; lsv = LYRIC_SHOW_VIEWPORT(widget); GtkStyleContext *context; GdkWindow *bin = gtk_viewport_get_bin_window(GTK_VIEWPORT(widget)); context = gtk_widget_get_style_context(widget); GTK_WIDGET_CLASS(lyric_show_viewport_parent_class)->draw(widget,cr); if(lsv->priv->is_pressed && gtk_cairo_should_draw_window(cr,bin)) { gint y0,y1; y0=y1 = gtk_widget_get_allocated_height(widget)/2.0;///lsv->priv->pos+lsv->priv->pressed_pos; gtk_render_line(context,cr,0,y0, gtk_widget_get_allocated_width(widget),y1); } return FALSE; }
/* This code was originally rendering anti-aliased using X primitives, and * now has been switched to draw anti-aliased using cairo. In general, the * closest correspondence between X rendering and cairo rendering is given * by offsetting the geometry by 0.5 pixels in both directions before rendering * with cairo. This is because X samples at the upper left corner of the * pixel while cairo averages over the entire pixel. However, in the cases * where the X rendering was an exact rectangle with no "jaggies" * we need to be a bit careful about applying the offset. We want to produce * the exact same pixel-aligned rectangle, rather than a rectangle with * fuzz around the edges. */ static void draw_op_draw_with_env (const MetaDrawOp *op, GtkStyleContext *context, cairo_t *cr, const MetaDrawInfo *info, MetaPositionExprEnv *env) { GdkRGBA color; cairo_save (cr); cairo_set_line_width (cr, 1.0); switch (op->type) { case META_DRAW_LINE: { gdouble x1, x2, y1, y2; meta_color_spec_render (op->data.line.color_spec, context, &color); gdk_cairo_set_source_rgba (cr, &color); if (op->data.line.width > 0) cairo_set_line_width (cr, op->data.line.width); if (op->data.line.dash_on_length > 0 && op->data.line.dash_off_length > 0) { double dash_list[2]; dash_list[0] = op->data.line.dash_on_length; dash_list[1] = op->data.line.dash_off_length; cairo_set_dash (cr, dash_list, 2, 0); } x1 = meta_draw_spec_parse_x_position (op->data.line.x1, env); y1 = meta_draw_spec_parse_y_position (op->data.line.y1, env); if (!op->data.line.x2 && !op->data.line.y2 && op->data.line.width == 0) { cairo_rectangle (cr, x1, y1, 1, 1); cairo_fill (cr); } else { if (op->data.line.x2) x2 = meta_draw_spec_parse_x_position (op->data.line.x2, env); else x2 = x1; if (op->data.line.y2) y2 = meta_draw_spec_parse_y_position (op->data.line.y2, env); else y2 = y1; /* This is one of the cases where we are matching the exact * pixel aligned rectangle produced by X; for zero-width lines * the generic algorithm produces the right result so we don't * need to handle them here. */ if ((y1 == y2 || x1 == x2) && op->data.line.width != 0) { double offset = op->data.line.width % 2 ? .5 : 0; if (y1 == y2) { cairo_move_to (cr, x1, y1 + offset); cairo_line_to (cr, x2, y2 + offset); } else { cairo_move_to (cr, x1 + offset, y1); cairo_line_to (cr, x2 + offset, y2); } } else { /* zero-width lines include both end-points in X, unlike wide lines */ if (op->data.line.width == 0) cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_move_to (cr, x1 + .5, y1 + .5); cairo_line_to (cr, x2 + .5, y2 + .5); } cairo_stroke (cr); } } break; case META_DRAW_RECTANGLE: { gdouble rx, ry, rwidth, rheight; meta_color_spec_render (op->data.rectangle.color_spec, context, &color); gdk_cairo_set_source_rgba (cr, &color); rx = meta_draw_spec_parse_x_position (op->data.rectangle.x, env); ry = meta_draw_spec_parse_y_position (op->data.rectangle.y, env); rwidth = meta_draw_spec_parse_size (op->data.rectangle.width, env); rheight = meta_draw_spec_parse_size (op->data.rectangle.height, env); /* Filled and stroked rectangles are the other cases * we pixel-align to X rasterization */ if (op->data.rectangle.filled) { cairo_rectangle (cr, rx, ry, rwidth, rheight); cairo_fill (cr); } else { cairo_rectangle (cr, rx + .5, ry + .5, rwidth, rheight); cairo_stroke (cr); } } break; case META_DRAW_ARC: { gdouble rx, ry, rwidth, rheight; double start_angle, end_angle; double center_x, center_y; meta_color_spec_render (op->data.arc.color_spec, context, &color); gdk_cairo_set_source_rgba (cr, &color); rx = meta_draw_spec_parse_x_position (op->data.arc.x, env); ry = meta_draw_spec_parse_y_position (op->data.arc.y, env); rwidth = meta_draw_spec_parse_size (op->data.arc.width, env); rheight = meta_draw_spec_parse_size (op->data.arc.height, env); start_angle = op->data.arc.start_angle * (M_PI / 180.) - (.5 * M_PI); /* start at 12 instead of 3 oclock */ end_angle = start_angle + op->data.arc.extent_angle * (M_PI / 180.); center_x = rx + (double)rwidth / 2. + .5; center_y = ry + (double)rheight / 2. + .5; cairo_save (cr); cairo_translate (cr, center_x, center_y); cairo_scale (cr, (double)rwidth / 2., (double)rheight / 2.); if (op->data.arc.extent_angle >= 0) cairo_arc (cr, 0, 0, 1, start_angle, end_angle); else cairo_arc_negative (cr, 0, 0, 1, start_angle, end_angle); cairo_restore (cr); if (op->data.arc.filled) { cairo_line_to (cr, center_x, center_y); cairo_fill (cr); } else cairo_stroke (cr); } break; case META_DRAW_CLIP: break; case META_DRAW_TINT: { gdouble rx, ry, rwidth, rheight; rx = meta_draw_spec_parse_x_position (op->data.tint.x, env); ry = meta_draw_spec_parse_y_position (op->data.tint.y, env); rwidth = meta_draw_spec_parse_size (op->data.tint.width, env); rheight = meta_draw_spec_parse_size (op->data.tint.height, env); meta_color_spec_render (op->data.tint.color_spec, context, &color); meta_alpha_gradient_spec_render (op->data.tint.alpha_spec, color, cr, rx, ry, rwidth, rheight); } break; case META_DRAW_GRADIENT: { gdouble rx, ry, rwidth, rheight; rx = meta_draw_spec_parse_x_position (op->data.gradient.x, env); ry = meta_draw_spec_parse_y_position (op->data.gradient.y, env); rwidth = meta_draw_spec_parse_size (op->data.gradient.width, env); rheight = meta_draw_spec_parse_size (op->data.gradient.height, env); meta_gradient_spec_render (op->data.gradient.gradient_spec, op->data.gradient.alpha_spec, cr, context, rx, ry, rwidth, rheight); } break; case META_DRAW_IMAGE: { gdouble scale; gdouble rx, ry, rwidth, rheight; cairo_surface_t *surface; scale = info->scale; cairo_scale (cr, 1.0 / scale, 1.0 / scale); if (op->data.image.pixbuf) { env->object_width = gdk_pixbuf_get_width (op->data.image.pixbuf); env->object_height = gdk_pixbuf_get_height (op->data.image.pixbuf); } rwidth = meta_draw_spec_parse_size (op->data.image.width, env) * scale; rheight = meta_draw_spec_parse_size (op->data.image.height, env) * scale; surface = draw_op_as_surface (op, context, info, rwidth, rheight); if (surface) { rx = meta_draw_spec_parse_x_position (op->data.image.x, env) * scale; ry = meta_draw_spec_parse_y_position (op->data.image.y, env) * scale; cairo_set_source_surface (cr, surface, rx, ry); if (op->data.image.alpha_spec) { cairo_pattern_t *pattern; cairo_translate (cr, rx, ry); cairo_scale (cr, rwidth, rheight); pattern = meta_alpha_gradient_spec_get_mask (op->data.image.alpha_spec); cairo_mask (cr, pattern); cairo_pattern_destroy (pattern); } else { cairo_paint (cr); } cairo_surface_destroy (surface); } } break; case META_DRAW_GTK_ARROW: { gdouble rx, ry, rwidth, rheight; double angle = 0, size; rx = meta_draw_spec_parse_x_position (op->data.gtk_arrow.x, env); ry = meta_draw_spec_parse_y_position (op->data.gtk_arrow.y, env); rwidth = meta_draw_spec_parse_size (op->data.gtk_arrow.width, env); rheight = meta_draw_spec_parse_size (op->data.gtk_arrow.height, env); size = MAX(rwidth, rheight); switch (op->data.gtk_arrow.arrow) { case GTK_ARROW_UP: angle = 0; break; case GTK_ARROW_RIGHT: angle = M_PI / 2; break; case GTK_ARROW_DOWN: angle = M_PI; break; case GTK_ARROW_LEFT: angle = 3 * M_PI / 2; break; case GTK_ARROW_NONE: return; default: break; } gtk_style_context_set_state (context, op->data.gtk_arrow.state); gtk_render_arrow (context, cr, angle, rx, ry, size); } break; case META_DRAW_GTK_BOX: { gdouble rx, ry, rwidth, rheight; rx = meta_draw_spec_parse_x_position (op->data.gtk_box.x, env); ry = meta_draw_spec_parse_y_position (op->data.gtk_box.y, env); rwidth = meta_draw_spec_parse_size (op->data.gtk_box.width, env); rheight = meta_draw_spec_parse_size (op->data.gtk_box.height, env); gtk_style_context_set_state (context, op->data.gtk_box.state); gtk_render_background (context, cr, rx, ry, rwidth, rheight); gtk_render_frame (context, cr, rx, ry, rwidth, rheight); } break; case META_DRAW_GTK_VLINE: { gdouble rx, ry1, ry2; rx = meta_draw_spec_parse_x_position (op->data.gtk_vline.x, env); ry1 = meta_draw_spec_parse_y_position (op->data.gtk_vline.y1, env); ry2 = meta_draw_spec_parse_y_position (op->data.gtk_vline.y2, env); gtk_style_context_set_state (context, op->data.gtk_vline.state); gtk_render_line (context, cr, rx, ry1, rx, ry2); } break; case META_DRAW_ICON: { gdouble rx, ry, rwidth, rheight; cairo_surface_t *surface; rwidth = meta_draw_spec_parse_size (op->data.icon.width, env); rheight = meta_draw_spec_parse_size (op->data.icon.height, env); surface = draw_op_as_surface (op, context, info, rwidth, rheight); if (surface) { rx = meta_draw_spec_parse_x_position (op->data.icon.x, env); ry = meta_draw_spec_parse_y_position (op->data.icon.y, env); cairo_set_source_surface (cr, surface, rx, ry); if (op->data.icon.alpha_spec) { cairo_pattern_t *pattern; cairo_translate (cr, rx, ry); cairo_scale (cr, rwidth, rheight); pattern = meta_alpha_gradient_spec_get_mask (op->data.icon.alpha_spec); cairo_mask (cr, pattern); cairo_pattern_destroy (pattern); } else { cairo_paint (cr); } cairo_surface_destroy (surface); } } break; case META_DRAW_TITLE: if (info->title_layout) { gdouble rx, ry; PangoRectangle ink_rect, logical_rect; meta_color_spec_render (op->data.title.color_spec, context, &color); gdk_cairo_set_source_rgba (cr, &color); rx = meta_draw_spec_parse_x_position (op->data.title.x, env); ry = meta_draw_spec_parse_y_position (op->data.title.y, env); if (op->data.title.ellipsize_width) { gdouble ellipsize_width; int right_bearing; ellipsize_width = meta_draw_spec_parse_x_position (op->data.title.ellipsize_width, env); /* HACK: meta_draw_spec_parse_x_position adds in env->rect.x, subtract out again */ ellipsize_width -= env->rect.x; pango_layout_set_width (info->title_layout, -1); pango_layout_get_pixel_extents (info->title_layout, &ink_rect, &logical_rect); /* Pango's idea of ellipsization is with respect to the logical rect. * correct for this, by reducing the ellipsization width by the overflow * of the un-ellipsized text on the right... it's always the visual * right we want regardless of bidi, since since the X we pass in to * cairo_move_to() is always the left edge of the line. */ right_bearing = (ink_rect.x + ink_rect.width) - (logical_rect.x + logical_rect.width); right_bearing = MAX (right_bearing, 0); ellipsize_width -= right_bearing; ellipsize_width = MAX (ellipsize_width, 0); /* Only ellipsizing when necessary is a performance optimization - * pango_layout_set_width() will force a relayout if it isn't the * same as the current width of -1. */ if (ellipsize_width < logical_rect.width) pango_layout_set_width (info->title_layout, PANGO_SCALE * ellipsize_width); } else if (rx - env->rect.x + env->title_width >= env->rect.width) { const double alpha_margin = 30.0; int text_space = env->rect.x + env->rect.width - (rx - env->rect.x) - env->right_width; double startalpha = 1.0 - (alpha_margin/((double)text_space)); cairo_pattern_t *linpat; linpat = cairo_pattern_create_linear (rx, ry, text_space, env->title_height); cairo_pattern_add_color_stop_rgba (linpat, 0, color.red, color.green, color.blue, color.alpha); cairo_pattern_add_color_stop_rgba (linpat, startalpha, color.red, color.green, color.blue, color.alpha); cairo_pattern_add_color_stop_rgba (linpat, 1, color.red, color.green, color.blue, 0); cairo_set_source(cr, linpat); cairo_pattern_destroy(linpat); } cairo_move_to (cr, rx, ry); pango_cairo_show_layout (cr, info->title_layout); /* Remove any ellipsization we might have set; will short-circuit * if the width is already -1 */ pango_layout_set_width (info->title_layout, -1); } break; case META_DRAW_OP_LIST: { MetaRectangleDouble d_rect; d_rect.x = meta_draw_spec_parse_x_position (op->data.op_list.x, env); d_rect.y = meta_draw_spec_parse_y_position (op->data.op_list.y, env); d_rect.width = meta_draw_spec_parse_size (op->data.op_list.width, env); d_rect.height = meta_draw_spec_parse_size (op->data.op_list.height, env); meta_draw_op_list_draw_with_style (op->data.op_list.op_list, context, cr, info, d_rect); } break; case META_DRAW_TILE: { gdouble rx, ry, rwidth, rheight; gdouble tile_xoffset, tile_yoffset; MetaRectangleDouble tile; rx = meta_draw_spec_parse_x_position (op->data.tile.x, env); ry = meta_draw_spec_parse_y_position (op->data.tile.y, env); rwidth = meta_draw_spec_parse_size (op->data.tile.width, env); rheight = meta_draw_spec_parse_size (op->data.tile.height, env); cairo_save (cr); cairo_rectangle (cr, rx, ry, rwidth, rheight); cairo_clip (cr); tile_xoffset = meta_draw_spec_parse_x_position (op->data.tile.tile_xoffset, env); tile_yoffset = meta_draw_spec_parse_y_position (op->data.tile.tile_yoffset, env); /* tile offset should not include x/y */ tile_xoffset -= env->rect.x; tile_yoffset -= env->rect.y; tile.width = meta_draw_spec_parse_size (op->data.tile.tile_width, env); tile.height = meta_draw_spec_parse_size (op->data.tile.tile_height, env); tile.x = rx - tile_xoffset; while (tile.x < (rx + rwidth)) { tile.y = ry - tile_yoffset; while (tile.y < (ry + rheight)) { meta_draw_op_list_draw_with_style (op->data.tile.op_list, context, cr, info, tile); tile.y += tile.height; } tile.x += tile.width; } cairo_restore (cr); } break; default: break; } cairo_restore (cr); }
static gboolean gtk_tearoff_menu_item_draw (GtkWidget *widget, cairo_t *cr) { GtkMenuItem *menu_item; GtkStateFlags state; GtkStyleContext *context; GtkBorder padding; gint x, y, width, height; gint right_max; guint border_width; GtkTextDirection direction; GtkWidget *parent; gdouble angle; menu_item = GTK_MENU_ITEM (widget); context = gtk_widget_get_style_context (widget); direction = gtk_widget_get_direction (widget); state = gtk_widget_get_state_flags (widget); border_width = gtk_container_get_border_width (GTK_CONTAINER (menu_item)); x = border_width; y = border_width; width = gtk_widget_get_allocated_width (widget) - border_width * 2; height = gtk_widget_get_allocated_height (widget) - border_width * 2; right_max = x + width; gtk_style_context_save (context); gtk_style_context_set_state (context, state); gtk_style_context_get_padding (context, state, &padding); if (state & GTK_STATE_FLAG_PRELIGHT) { gtk_render_background (context, cr, x, y, width, height); gtk_render_frame (context, cr, x, y, width, height); } parent = gtk_widget_get_parent (widget); if (GTK_IS_MENU (parent) && gtk_menu_get_tearoff_state (GTK_MENU (parent))) { gint arrow_x; if (menu_item->priv->toggle_size > ARROW_SIZE) { if (direction == GTK_TEXT_DIR_LTR) { arrow_x = x + (menu_item->priv->toggle_size - ARROW_SIZE)/2; angle = (3 * G_PI) / 2; } else { arrow_x = x + width - menu_item->priv->toggle_size + (menu_item->priv->toggle_size - ARROW_SIZE)/2; angle = G_PI / 2; } x += menu_item->priv->toggle_size + BORDER_SPACING; } else { if (direction == GTK_TEXT_DIR_LTR) { arrow_x = ARROW_SIZE / 2; angle = (3 * G_PI) / 2; } else { arrow_x = x + width - 2 * ARROW_SIZE + ARROW_SIZE / 2; angle = G_PI / 2; } x += 2 * ARROW_SIZE; } gtk_render_arrow (context, cr, angle, arrow_x, height / 2 - 5, ARROW_SIZE); } while (x < right_max) { gint x1, x2; if (direction == GTK_TEXT_DIR_LTR) { x1 = x; x2 = MIN (x + TEAR_LENGTH, right_max); } else { x1 = right_max - x; x2 = MAX (right_max - x - TEAR_LENGTH, 0); } gtk_render_line (context, cr, x1, y + (height - padding.bottom) / 2, x2, y + (height - padding.bottom) / 2); x += 2 * TEAR_LENGTH; } gtk_style_context_restore (context); return FALSE; }