void gofu_render_grid_starpoint_round (cairo_t * cr) { cairo_arc (cr, 0., 0., 1., 0., 2 * G_PI); cairo_close_path (cr); }
static void ppg_ruler_draw_arrow (PpgRuler *ruler) { PpgRulerPrivate *priv; GtkStyle *style; GdkColor base_light; GdkColor base_dark; GdkColor hl_light; GdkColor hl_dark; cairo_t *cr; gint half; gint line_width; gint center; gint middle; gdouble top; gdouble bottom; gdouble left; gdouble right; g_return_if_fail(PPG_IS_RULER(ruler)); priv = ruler->priv; style = gtk_widget_get_style(GTK_WIDGET(ruler)); cr = gdk_cairo_create(priv->arrow); cairo_save(cr); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_rectangle(cr, 0, 0, ARROW_SIZE, ARROW_SIZE); cairo_fill(cr); cairo_restore(cr); center = middle = half = ARROW_SIZE / 2; line_width = half / 6; base_light = style->light[GTK_STATE_SELECTED]; base_dark = style->dark[GTK_STATE_SELECTED]; hl_light = style->light[GTK_STATE_SELECTED]; hl_dark = style->mid[GTK_STATE_SELECTED]; top = middle - half + line_width + 0.5; bottom = middle + half - line_width + 0.5; left = center - half + line_width + 0.5; right = center +half - line_width - 0.5; cairo_set_line_width(cr, line_width); cairo_move_to(cr, left + line_width, top + line_width); cairo_line_to(cr, right + line_width, top + line_width); cairo_line_to(cr, right + line_width, middle + line_width); cairo_line_to(cr, center + line_width, bottom + line_width); cairo_line_to(cr, left + line_width, middle + line_width); cairo_line_to(cr, left + line_width, top + line_width); cairo_close_path(cr); cairo_set_source_rgba(cr, 0, 0, 0, 0.5); cairo_fill(cr); cairo_move_to(cr, left, top); cairo_line_to(cr, center, top); cairo_line_to(cr, center, bottom); cairo_line_to(cr, left, middle); cairo_line_to(cr, left, top); cairo_close_path(cr); gdk_cairo_set_source_color(cr, &base_light); cairo_fill(cr); cairo_move_to(cr, center, top); cairo_line_to(cr, right, top); cairo_line_to(cr, right, middle); cairo_line_to(cr, center, bottom); cairo_line_to(cr, center, top); cairo_close_path(cr); gdk_cairo_set_source_color(cr, &base_light); cairo_fill_preserve(cr); cairo_set_source_rgba(cr, base_dark.red / 65535.0, base_dark.green / 65535.0, base_dark.blue / 65535.0, 0.5); cairo_fill(cr); cairo_move_to(cr, left + line_width, top + line_width); cairo_line_to(cr, right - line_width, top + line_width); cairo_line_to(cr, right - line_width, middle); cairo_line_to(cr, center, bottom - line_width - 0.5); cairo_line_to(cr, left + line_width, middle); cairo_line_to(cr, left + line_width, top + line_width); cairo_close_path(cr); gdk_cairo_set_source_color(cr, &hl_light); cairo_stroke(cr); cairo_move_to(cr, left, top); cairo_line_to(cr, right, top); cairo_line_to(cr, right, middle); cairo_line_to(cr, center, bottom); cairo_line_to(cr, left, middle); cairo_line_to(cr, left, top); cairo_close_path(cr); gdk_cairo_set_source_color(cr, &base_dark); cairo_stroke(cr); cairo_destroy(cr); }
static void _paint_lyrics (OlScrollWindow *scroll, cairo_t *cr) { ol_assert (OL_IS_SCROLL_WINDOW (scroll)); GtkWidget *widget = GTK_WIDGET (scroll); ol_assert (GTK_WIDGET_REALIZED (widget)); OlScrollWindowPrivate *priv = OL_SCROLL_WINDOW_GET_PRIVATE (scroll); int line_height = ol_scroll_window_get_font_height (scroll) + priv->line_margin; int count = ol_scroll_window_compute_line_count (scroll); gint width, height; gdk_drawable_get_size (gtk_widget_get_window (GTK_WIDGET (scroll)), &width, &height); /* set the font */ PangoLayout *layout = _get_pango (scroll, cr); /* paint the lyrics*/ cairo_save (cr); cairo_new_path (cr); cairo_rectangle (cr, priv->padding_x, 0, width - priv->padding_x * 2, height - priv->padding_y * 2); cairo_close_path (cr); cairo_clip (cr); int i; gint current_lyric_id; gint lrc_y; _calc_paint_pos (scroll, ¤t_lyric_id, &lrc_y); int begin = current_lyric_id - count / 2; int end = current_lyric_id + count / 2 + 1; int ypos = height / 2 - lrc_y - (count / 2 + 1) * line_height; cairo_set_source_rgb(cr, priv->inactive_color.r, priv->inactive_color.g, priv->inactive_color.b); if (scroll->whole_lyrics != NULL) { for (i = begin; i < end; i++) { ypos += line_height; if (i < 0) continue; if (i >= scroll->whole_lyrics->len) break; pango_layout_set_text (layout, g_ptr_array_index (scroll->whole_lyrics, i), -1); cairo_save (cr); double ratio = _get_active_color_ratio (scroll, i); double alpha = 1.0; if (ypos < line_height / 2.0 + priv->padding_y) alpha = 1.0 - (line_height / 2.0 + priv->padding_y - ypos) * 1.0 / line_height * 2; else if (ypos > height - line_height * 1.5 - priv->padding_y) alpha = (height - line_height - priv->padding_y - ypos) * 1.0 / line_height * 2; if (alpha < 0.0) alpha = 0.0; cairo_set_source_rgba (cr, priv->active_color.r * ratio + priv->inactive_color.r * (1 - ratio), priv->active_color.g * ratio + priv->inactive_color.g * (1 - ratio), priv->active_color.b * ratio + priv->inactive_color.b * (1 - ratio), alpha); cairo_move_to (cr, priv->padding_x, ypos); pango_cairo_update_layout (cr, layout); pango_cairo_show_layout (cr, layout); cairo_restore (cr); } } g_object_unref (layout); cairo_reset_clip (cr); cairo_restore (cr); }
int plotstuff_close_path(plot_args_t* pargs) { assert(pargs->cairo); cairo_close_path(pargs->cairo); return 0; }
void ofCairoRenderer::draw(ofSubPath & path){ if(!surface || !cr) return; const vector<ofSubPath::Command> & commands = path.getCommands(); cairo_new_sub_path(cr); for(int i=0; i<(int)commands.size(); i++){ switch(commands[i].type){ case ofSubPath::Command::lineTo: curvePoints.clear(); cairo_line_to(cr,commands[i].to.x,commands[i].to.y); break; case ofSubPath::Command::curveTo: curvePoints.push_back(commands[i].to); //code adapted from ofxVectorGraphics to convert catmull rom to bezier if(curvePoints.size()==4){ ofPoint p1=curvePoints[0]; ofPoint p2=curvePoints[1]; ofPoint p3=curvePoints[2]; ofPoint p4=curvePoints[3]; //SUPER WEIRD MAGIC CONSTANT = 1/6 (this works 100% can someone explain it?) ofPoint cp1 = p2 + ( p3 - p1 ) * (1.0/6); ofPoint cp2 = p3 + ( p2 - p4 ) * (1.0/6); cairo_curve_to( cr, cp1.x, cp1.y, cp2.x, cp2.y, p3.x, p3.y ); curvePoints.pop_front(); } break; case ofSubPath::Command::bezierTo: curvePoints.clear(); cairo_curve_to(cr,commands[i].cp1.x,commands[i].cp1.y,commands[i].cp2.x,commands[i].cp2.y,commands[i].to.x,commands[i].to.y); break; case ofSubPath::Command::quadBezierTo: curvePoints.clear(); cairo_curve_to(cr,commands[i].cp1.x,commands[i].cp1.y,commands[i].cp2.x,commands[i].cp2.y,commands[i].to.x,commands[i].to.y); break; case ofSubPath::Command::arc: curvePoints.clear(); // elliptic arcs not directly supported in cairo, lets scale y if(commands[i].radiusX!=commands[i].radiusY){ float ellipse_ratio = commands[i].radiusY/commands[i].radiusX; pushMatrix(); translate(0,-commands[i].to.y*ellipse_ratio); scale(1,ellipse_ratio); translate(0,commands[i].to.y/ellipse_ratio); cairo_arc(cr,commands[i].to.x,commands[i].to.y,commands[i].radiusX,commands[i].angleBegin*DEG_TO_RAD,commands[i].angleEnd*DEG_TO_RAD); //cairo_set_matrix(cr,&stored_matrix); popMatrix(); }else{ cairo_arc(cr,commands[i].to.x,commands[i].to.y,commands[i].radiusX,commands[i].angleBegin*DEG_TO_RAD,commands[i].angleEnd*DEG_TO_RAD); } break; } } if(path.isClosed()){ cairo_close_path(cr); } }
/*********************************************** * do_hc_draw_arrow - * * A simple routine to draw a hc style * arrow using the passed Color. * * Taken in part from smooth, it was based on * XFCE's & CleanIce draw arrow routines, * both which were based on ThinIce's. ***********************************************/ void do_hc_draw_arrow (cairo_t *canvas, CairoColor * color, GtkArrowType arrow_type, gboolean fill, gint x, gint y, gint width, gint height) { gint aw = width, ah = height; GdkPoint points[3]; switch (arrow_type) { case GTK_ARROW_UP: case GTK_ARROW_DOWN: { gdouble tmp=((aw+1)/2) - ((height%2)?1:0); if (tmp > ah) { aw = 2*ah - 1 - ((height%2)?1:0); ah = (aw+1)/2; } else { ah = (gint) tmp; aw = 2*ah - 1; } if ((aw < 5) || (ah < 3)) { aw = 5; ah = 3; } x += (width - aw) / 2 ; y += (height - ah) / 2; width = aw; height = ah; width += width % 2 - 1; points[0].x = x; points[1].x = x + width - 1; points[2].x = x + ((height - 1) - (height - (1 + width / 2))); points[0].y = points[1].y = y; points[2].y = y + height - 1; if (arrow_type == GTK_ARROW_UP) { gint flip = points[1].y; points[0].y = points[1].y = points[2].y; points[2].y = flip; } } break; case GTK_ARROW_LEFT: case GTK_ARROW_RIGHT: { gdouble tmp=((ah+1)/2) - ((width%2)?1:0); if (tmp > aw) { ah = 2*aw - 1 - ((width%2)?1:0); aw = (ah+1)/2; } else { aw = (gint) tmp; ah = 2*aw - 1; } if ((ah < 5) || (aw < 3)) { ah = 5; aw = 3; } x += (width - aw) / 2 ; y += (height - ah) / 2; width = aw; height = ah; height += height % 2 - 1; points[0].y = y; points[1].y = y + height - 1; points[2].y = y + ((width - 1) - (width - (1 + height / 2))); points[0].x = points[1].x = x; points[2].x = x + width - 1; if (arrow_type == GTK_ARROW_LEFT) { gint flip = points[0].x; points[0].x = points[1].x = points[2].x; points[2].x = flip; } } break; default: { return; } } cairo_save(canvas); ge_cairo_set_color(canvas, color); cairo_set_line_width (canvas, 0.5); cairo_move_to(canvas, points[0].x + 0.5, points[0].y + 0.5); cairo_line_to(canvas, points[1].x + 0.5, points[1].y + 0.5); cairo_line_to(canvas, points[2].x + 0.5, points[2].y + 0.5); cairo_close_path(canvas); if (fill) { cairo_stroke_preserve(canvas); cairo_fill(canvas); } else { cairo_stroke(canvas); } cairo_restore(canvas); }
static gboolean dt_iop_zonesystem_bar_draw(GtkWidget *widget, cairo_t *crf, dt_iop_module_t *self) { dt_iop_zonesystem_gui_data_t *g = (dt_iop_zonesystem_gui_data_t *)self->gui_data; dt_iop_zonesystem_params_t *p = (dt_iop_zonesystem_params_t *)self->params; const int inset = DT_ZONESYSTEM_INSET; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width, height = allocation.height; cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); /* clear background */ cairo_set_source_rgb(cr, .15, .15, .15); cairo_paint(cr); /* translate and scale */ width -= 2 * inset; height -= 2 * inset; cairo_save(cr); cairo_translate(cr, inset, inset); cairo_scale(cr, width, height); /* render the bars */ float zonemap[MAX_ZONE_SYSTEM_SIZE] = { 0 }; _iop_zonesystem_calculate_zonemap(p, zonemap); float s = (1. / (p->size - 2)); cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); for(int i = 0; i < p->size - 1; i++) { /* draw the reference zone */ float z = s * i; cairo_rectangle(cr, (1. / (p->size - 1)) * i, 0, (1. / (p->size - 1)), DT_ZONESYSTEM_REFERENCE_SPLIT - DT_ZONESYSTEM_BAR_SPLIT_WIDTH); cairo_set_source_rgb(cr, z, z, z); cairo_fill(cr); /* draw zone mappings */ cairo_rectangle(cr, zonemap[i], DT_ZONESYSTEM_REFERENCE_SPLIT + DT_ZONESYSTEM_BAR_SPLIT_WIDTH, (zonemap[i + 1] - zonemap[i]), 1.0 - DT_ZONESYSTEM_REFERENCE_SPLIT); cairo_set_source_rgb(cr, z, z, z); cairo_fill(cr); } cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT); cairo_restore(cr); /* render zonebar control lines */ cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); cairo_set_line_width(cr, 1.); cairo_rectangle(cr, inset, inset, width, height); cairo_set_source_rgb(cr, .1, .1, .1); cairo_stroke(cr); cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT); /* render control points handles */ cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.)); const float arrw = DT_PIXEL_APPLY_DPI(7.0f); for(int k = 1; k < p->size - 1; k++) { float nzw = zonemap[k + 1] - zonemap[k]; float pzw = zonemap[k] - zonemap[k - 1]; if((((g->mouse_x / width) > (zonemap[k] - (pzw / 2.0))) && ((g->mouse_x / width) < (zonemap[k] + (nzw / 2.0)))) || p->zone[k] != -1) { gboolean is_under_mouse = ((width * zonemap[k]) - arrw * .5f < g->mouse_x && (width * zonemap[k]) + arrw * .5f > g->mouse_x); cairo_move_to(cr, inset + (width * zonemap[k]), height + (2 * inset) - 1); cairo_rel_line_to(cr, -arrw * .5f, 0); cairo_rel_line_to(cr, arrw * .5f, -arrw); cairo_rel_line_to(cr, arrw * .5f, arrw); cairo_close_path(cr); if(is_under_mouse) cairo_fill(cr); else cairo_stroke(cr); } } /* push mem surface into widget */ cairo_destroy(cr); cairo_set_source_surface(crf, cst, 0, 0); cairo_paint(crf); cairo_surface_destroy(cst); return TRUE; }
void gschem_cairo_center_box (GSCHEM_TOPLEVEL *w_current, int center_width, int line_width, int x, int y, int half_width, int half_height) { int s_center_width, s_line_width; int s_width, s_height; double s_half_width, s_half_height; int s_x, s_y; int even_center_width; int even_line_width; int even_width, even_height; double x1, y1, x2, y2; double center_offset; int do_width_hint = TRUE; int do_height_hint = TRUE; WORLDtoSCREEN (w_current, x, y, &s_x, &s_y); s_width = SCREENabs (w_current, 2 * half_width); s_height = SCREENabs (w_current, 2 * half_height); even_width = (s_width % 2 == 0); even_height = (s_width % 2 == 0); s_half_width = (double) s_width / 2.; s_half_height = (double) s_height / 2.; #if 0 /* Not as nice an effect as with arcs */ /* Switch off radius hinting for small radii. If we don't, then we get * a very abrupt transition once the box reaches a single pixel size. */ if (s_half_width <= 1.) do_width_hint = FALSE; if (s_half_height <= 1.) do_height_hint = FALSE; #endif /* Hint the center of the box based on where a line * of thickness center_width (world) would drawn */ s_center_width = screen_width (w_current, center_width); even_center_width = (center_width == -1 || (s_center_width % 2) == 0); center_offset = even_center_width ? 0. : 0.5; /* Hint the half-widths to land the stroke on the pixel grid */ s_line_width = screen_width (w_current, line_width); even_line_width = (line_width == -1 || (s_line_width % 2) == 0); if (do_width_hint) s_half_width += ((even_center_width == even_line_width) == even_width ) ? 0. : 0.5; if (do_height_hint) s_half_height += ((even_center_width == even_line_width) == even_height) ? 0. : 0.5; x1 = (double) s_x + center_offset - s_half_width; y1 = (double) s_y + center_offset - s_half_height; x2 = (double) s_x + center_offset + s_half_width; y2 = (double) s_y + center_offset + s_half_height; /* Allow filled boxes (inferred from line_width == -1) * to touch an extra pixel, so the filled span is inclusive */ if (line_width == -1) { x2 += 1; y2 += 1; } cairo_move_to (w_current->cr, x2, y2); cairo_line_to (w_current->cr, x1, y2); cairo_line_to (w_current->cr, x1, y1); cairo_line_to (w_current->cr, x2, y1); cairo_close_path (w_current->cr); }
/* * This function must be called with a range of samples, and a desired * width and height. * It will average samples if needed. */ static PyObject * py_fill_surface (PyObject * self, PyObject * args) { PyObject *samples; PyObject *sampleObj; int length, i; double sample; cairo_surface_t *surface; cairo_t *ctx; int width, height; float pixelsPerSample; float currentPixel; int samplesInAccum; float x = 0.; double accum; if (!PyArg_ParseTuple (args, "O!ii", &PyList_Type, &samples, &width, &height)) return NULL; length = PyList_Size (samples); surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); ctx = cairo_create (surface); cairo_set_source_rgb (ctx, 0.2, 0.6, 0.0); cairo_set_line_width (ctx, 0.5); cairo_move_to (ctx, 0, height); pixelsPerSample = width / (float) length; currentPixel = 0.; samplesInAccum = 0; accum = 0.; for (i = 0; i < length; i++) { /* Guaranteed to return something */ sampleObj = PyList_GetItem (samples, i); sample = PyFloat_AsDouble (sampleObj); /* If the object was not a float or convertible to float */ if (PyErr_Occurred ()) { cairo_surface_finish (surface); Py_DECREF (samples); return NULL; } currentPixel += pixelsPerSample; samplesInAccum += 1; accum += sample; if (currentPixel > 1.0) { accum /= samplesInAccum; cairo_line_to (ctx, x, height - accum); accum = 0; currentPixel -= 1.0; samplesInAccum = 0; } x += pixelsPerSample; } Py_DECREF (samples); cairo_line_to (ctx, width, height); cairo_close_path (ctx); cairo_fill_preserve (ctx); return PycairoSurface_FromSurface (surface, NULL); }
void gui_post_expose(struct dt_iop_module_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { dt_develop_t *dev = self->dev; dt_iop_graduatednd_gui_data_t *g = (dt_iop_graduatednd_gui_data_t *)self->gui_data; dt_iop_graduatednd_params_t *p = (dt_iop_graduatednd_params_t *)self->params; float wd = dev->preview_pipe->backbuf_width; float ht = dev->preview_pipe->backbuf_height; float zoom_y = dt_control_get_dev_zoom_y(); float zoom_x = dt_control_get_dev_zoom_x(); dt_dev_zoom_t zoom = dt_control_get_dev_zoom(); int closeup = dt_control_get_dev_closeup(); float zoom_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2 : 1, 1); cairo_translate(cr, width / 2.0, height / 2.0f); cairo_scale(cr, zoom_scale, zoom_scale); cairo_translate(cr, -.5f * wd - zoom_x * wd, -.5f * ht - zoom_y * ht); // we get the extremities of the line if(g->define == 0) { if(!set_points_from_grad(self, &g->xa, &g->ya, &g->xb, &g->yb, p->rotation, p->offset)) return; g->define = 1; } float xa = g->xa * wd, xb = g->xb * wd, ya = g->ya * ht, yb = g->yb * ht; // the lines cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); if(g->selected == 3 || g->dragging == 3) cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(5.0) / zoom_scale); else cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(3.0) / zoom_scale); cairo_set_source_rgba(cr, .3, .3, .3, .8); cairo_move_to(cr, xa, ya); cairo_line_to(cr, xb, yb); cairo_stroke(cr); if(g->selected == 3 || g->dragging == 3) cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0) / zoom_scale); else cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.0) / zoom_scale); cairo_set_source_rgba(cr, .8, .8, .8, .8); cairo_move_to(cr, xa, ya); cairo_line_to(cr, xb, yb); cairo_stroke(cr); // the extremities float x1, y1, x2, y2; float l = sqrt((xb - xa) * (xb - xa) + (yb - ya) * (yb - ya)); const float ext = wd * 0.01f / zoom_scale; x1 = xa + (xb - xa) * ext / l; y1 = ya + (yb - ya) * ext / l; x2 = (xa + x1) / 2.0; y2 = (ya + y1) / 2.0; y2 += (x1 - xa); x2 -= (y1 - ya); cairo_move_to(cr, xa, ya); cairo_line_to(cr, x1, y1); cairo_line_to(cr, x2, y2); cairo_close_path(cr); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.0) / zoom_scale); if(g->selected == 1 || g->dragging == 1) cairo_set_source_rgba(cr, .8, .8, .8, 1.0); else cairo_set_source_rgba(cr, .8, .8, .8, .5); cairo_fill_preserve(cr); if(g->selected == 1 || g->dragging == 1) cairo_set_source_rgba(cr, .3, .3, .3, 1.0); else cairo_set_source_rgba(cr, .3, .3, .3, .5); cairo_stroke(cr); x1 = xb - (xb - xa) * ext / l; y1 = yb - (yb - ya) * ext / l; x2 = (xb + x1) / 2.0; y2 = (yb + y1) / 2.0; y2 += (xb - x1); x2 -= (yb - y1); cairo_move_to(cr, xb, yb); cairo_line_to(cr, x1, y1); cairo_line_to(cr, x2, y2); cairo_close_path(cr); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.0) / zoom_scale); if(g->selected == 2 || g->dragging == 2) cairo_set_source_rgba(cr, .8, .8, .8, 1.0); else cairo_set_source_rgba(cr, .8, .8, .8, .5); cairo_fill_preserve(cr); if(g->selected == 2 || g->dragging == 2) cairo_set_source_rgba(cr, .3, .3, .3, 1.0); else cairo_set_source_rgba(cr, .3, .3, .3, .5); cairo_stroke(cr); }
void Path::closeSubpath() { cairo_t* cr = ensurePlatformPath()->context(); cairo_close_path(cr); }
void ofCairoRenderer::draw(const ofPath::Command & command) const{ if(!surface || !cr) return; ofCairoRenderer * mut_this = const_cast<ofCairoRenderer*>(this); switch(command.type){ case ofPath::Command::moveTo: curvePoints.clear(); cairo_move_to(cr,command.to.x,command.to.y); break; case ofPath::Command::lineTo: curvePoints.clear(); cairo_line_to(cr,command.to.x,command.to.y); break; case ofPath::Command::curveTo: curvePoints.push_back(command.to); //code adapted from ofxVectorGraphics to convert catmull rom to bezier if(curvePoints.size()==4){ ofPoint p1=curvePoints[0]; ofPoint p2=curvePoints[1]; ofPoint p3=curvePoints[2]; ofPoint p4=curvePoints[3]; //SUPER WEIRD MAGIC CONSTANT = 1/6 (this works 100% can someone explain it?) ofPoint cp1 = p2 + ( p3 - p1 ) * (1.0f/6.f); ofPoint cp2 = p3 + ( p2 - p4 ) * (1.0f/6.f); cairo_curve_to( cr, cp1.x, cp1.y, cp2.x, cp2.y, p3.x, p3.y ); curvePoints.pop_front(); } break; case ofPath::Command::bezierTo: curvePoints.clear(); cairo_curve_to(cr,command.cp1.x,command.cp1.y,command.cp2.x,command.cp2.y,command.to.x,command.to.y); break; case ofPath::Command::quadBezierTo: curvePoints.clear(); cairo_curve_to(cr,command.cp1.x,command.cp1.y,command.cp2.x,command.cp2.y,command.to.x,command.to.y); break; case ofPath::Command::arc: curvePoints.clear(); // elliptic arcs not directly supported in cairo, lets scale y if(command.radiusX!=command.radiusY){ float ellipse_ratio = command.radiusY/command.radiusX; mut_this->pushMatrix(); mut_this->translate(0,-command.to.y*ellipse_ratio); mut_this->scale(1,ellipse_ratio); mut_this->translate(0,command.to.y/ellipse_ratio); cairo_arc(cr,command.to.x,command.to.y,command.radiusX,command.angleBegin*DEG_TO_RAD,command.angleEnd*DEG_TO_RAD); //cairo_set_matrix(cr,&stored_matrix); mut_this->popMatrix(); }else{ cairo_arc(cr,command.to.x,command.to.y,command.radiusX,command.angleBegin*DEG_TO_RAD,command.angleEnd*DEG_TO_RAD); } break; case ofPath::Command::arcNegative: curvePoints.clear(); // elliptic arcs not directly supported in cairo, lets scale y if(command.radiusX!=command.radiusY){ float ellipse_ratio = command.radiusY/command.radiusX; mut_this->pushMatrix(); mut_this->translate(0,-command.to.y*ellipse_ratio); mut_this->scale(1,ellipse_ratio); mut_this->translate(0,command.to.y/ellipse_ratio); cairo_arc_negative(cr,command.to.x,command.to.y,command.radiusX,command.angleBegin*DEG_TO_RAD,command.angleEnd*DEG_TO_RAD); //cairo_set_matrix(cr,&stored_matrix); mut_this->popMatrix(); }else{ cairo_arc_negative(cr,command.to.x,command.to.y,command.radiusX,command.angleBegin*DEG_TO_RAD,command.angleEnd*DEG_TO_RAD); } break; case ofPath::Command::close: cairo_close_path(cr); break; } }
void gt_graphics_cairo_draw_box(GtGraphics *gg, double x, double y, double width, double height, GtColor fill_color, ArrowStatus arrow_status, double arrow_width, double stroke_width, GtColor stroke_color, bool dashed) { GtGraphicsCairo *g = gt_graphics_cairo_cast(gg); double dashes[]={2.0}; bool widthdiff_geq0; gt_assert(g); /* save cairo context */ cairo_save(g->cr); cairo_rectangle(g->cr, rnd_to_nhalf(g->margin_x), g->margin_y, rnd_to_nhalf(g->width-2*g->margin_x), g->height-2*g->margin_y); cairo_clip(g->cr); widthdiff_geq0 = gt_double_smaller_double(0, width - arrow_width); /* construct shape of the box or arrow */ switch (arrow_status) { case ARROW_RIGHT: cairo_move_to(g->cr, rnd_to_nhalf(x), rnd_to_nhalf(y)); if (widthdiff_geq0) cairo_line_to(g->cr, x + width - arrow_width, rnd_to_nhalf(y)); cairo_line_to(g->cr, rnd_to_nhalf(x + width), rnd_to_nhalf(y + height / 2)); if (widthdiff_geq0) cairo_line_to(g->cr, x + width - arrow_width, rnd_to_nhalf(y + height)); cairo_line_to(g->cr, rnd_to_nhalf(x), rnd_to_nhalf(y + height)); cairo_close_path(g->cr); break; case ARROW_LEFT: cairo_move_to(g->cr, rnd_to_nhalf(x + width), rnd_to_nhalf(y)); if (widthdiff_geq0) { cairo_line_to(g->cr, rnd_to_nhalf(x + arrow_width), rnd_to_nhalf(y)); } cairo_line_to(g->cr, rnd_to_nhalf(x), rnd_to_nhalf(y + height / 2)); if (widthdiff_geq0) { cairo_line_to(g->cr, rnd_to_nhalf(x + arrow_width), rnd_to_nhalf(y + height)); } cairo_line_to(g->cr, rnd_to_nhalf(x + width), rnd_to_nhalf(y + height)); cairo_close_path(g->cr); break; case ARROW_BOTH: cairo_move_to(g->cr, rnd_to_nhalf(x), rnd_to_nhalf(y + height/2)); if (gt_double_smaller_double(width, 2*arrow_width)) { cairo_line_to(g->cr, rnd_to_nhalf(x + width/2), rnd_to_nhalf(y)); cairo_line_to(g->cr, rnd_to_nhalf(x + width), rnd_to_nhalf(y + height/2)); cairo_line_to(g->cr, rnd_to_nhalf(x + width/2), rnd_to_nhalf(y + height)); } else { cairo_line_to(g->cr, rnd_to_nhalf(x + arrow_width), rnd_to_nhalf(y)); cairo_line_to(g->cr, rnd_to_nhalf(x + width - arrow_width), rnd_to_nhalf(y)); cairo_line_to(g->cr, rnd_to_nhalf(x + width), rnd_to_nhalf(y + height/2)); cairo_line_to(g->cr, rnd_to_nhalf(x + width - arrow_width), rnd_to_nhalf(y + height)); cairo_line_to(g->cr, rnd_to_nhalf(x + arrow_width), y + height); } cairo_close_path(g->cr); break; case ARROW_NONE: cairo_rectangle(g->cr, rnd_to_nhalf(x), rnd_to_nhalf(y), width, height); } /* fill area */ cairo_set_source_rgba(g->cr, fill_color.red, fill_color.green, fill_color.blue, fill_color.alpha); cairo_fill_preserve(g->cr); /* draw outline */ cairo_set_line_width(g->cr, stroke_width); cairo_set_source_rgba(g->cr, stroke_color.red, stroke_color.green, stroke_color.blue, stroke_color.alpha); if (dashed) cairo_set_dash(g->cr, dashes, 1, (double) 0); cairo_stroke(g->cr); /* restore cairo context */ cairo_restore(g->cr); }
static gboolean dt_iop_levels_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { dt_iop_module_t *self = (dt_iop_module_t *)user_data; dt_iop_levels_gui_data_t *c = (dt_iop_levels_gui_data_t *)self->gui_data; dt_iop_levels_params_t *p = (dt_iop_levels_params_t *)self->params; const int inset = DT_GUI_CURVE_EDITOR_INSET; int width = widget->allocation.width, height = widget->allocation.height; cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); // clear bg cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); cairo_translate(cr, inset, inset); width -= 2*inset; height -= 2*inset; cairo_set_line_width(cr, 1.0); cairo_set_source_rgb (cr, .1, .1, .1); cairo_rectangle(cr, 0, 0, width, height); cairo_stroke(cr); cairo_set_source_rgb (cr, .3, .3, .3); cairo_rectangle(cr, 0, 0, width, height); cairo_fill(cr); // draw grid cairo_set_line_width(cr, .4); cairo_set_source_rgb (cr, .1, .1, .1); dt_draw_vertical_lines(cr, 4, 0, 0, width, height); // Drawing the vertical line indicators cairo_set_line_width(cr, 2.); for(int k = 0; k < 3; k++) { if(k == c->handle_move && c->mouse_x > 0) cairo_set_source_rgb(cr, 1, 1, 1); else cairo_set_source_rgb(cr, .7, .7, .7); cairo_move_to(cr, width*p->levels[k], height); cairo_rel_line_to(cr, 0, -height); cairo_stroke(cr); } // draw x positions cairo_set_line_width(cr, 1.); const float arrw = 7.0f; for(int k=0; k<3; k++) { switch(k) { case 0: cairo_set_source_rgb(cr, 0, 0, 0); break; case 1: cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); break; default: cairo_set_source_rgb(cr, 1, 1, 1); break; } cairo_move_to(cr, width*p->levels[k], height+inset-1); cairo_rel_line_to(cr, -arrw*.5f, 0); cairo_rel_line_to(cr, arrw*.5f, -arrw); cairo_rel_line_to(cr, arrw*.5f, arrw); cairo_close_path(cr); if(c->handle_move == k && c->mouse_x > 0) cairo_fill(cr); else cairo_stroke(cr); } cairo_translate(cr, 0, height); // draw lum histogram in background // only if the module is enabled if (self->enabled) { dt_develop_t *dev = darktable.develop; float *hist, hist_max; hist = dev->histogram_pre_levels; hist_max = dev->histogram_pre_levels_max; if(hist_max > 0) { cairo_save(cr); cairo_scale(cr, width/63.0, -(height-5)/(float)hist_max); cairo_set_source_rgba(cr, .2, .2, .2, 0.5); dt_draw_histogram_8(cr, hist, 3); cairo_restore(cr); } } // Cleaning up cairo_destroy(cr); cairo_t *cr_pixmap = gdk_cairo_create(gtk_widget_get_window(widget)); cairo_set_source_surface (cr_pixmap, cst, 0, 0); cairo_paint(cr_pixmap); cairo_destroy(cr_pixmap); cairo_surface_destroy(cst); return TRUE; }
void structGraphicsScreen :: v_polyline (long numberOfPoints, double *xyDC, bool close) { #if cairo if (duringXor) { #if ALLOW_GDK_DRAWING gdkPrepareLine (this); for (long i = 0; i < numberOfPoints - 1; i ++) { gdk_draw_line (our d_window, our d_gdkGraphicsContext, xyDC [i + i], xyDC [i + i + 1], xyDC [i + i + 2], xyDC [i + i + 3]); } gdkRevertLine (this); gdk_flush (); #endif } else { if (our d_cairoGraphicsContext == NULL) return; cairoPrepareLine (this); // cairo_new_path (d_cairoGraphicsContext); // move_to() automatically creates a new path cairo_move_to (our d_cairoGraphicsContext, xyDC [0], xyDC [1]); for (long i = 1; i < numberOfPoints; i ++) { cairo_line_to (our d_cairoGraphicsContext, xyDC [i + i], xyDC [i + i + 1]); } if (close) cairo_close_path (our d_cairoGraphicsContext); cairo_stroke (our d_cairoGraphicsContext); cairoRevertLine (this); } #elif win winPrepareLine (this); POINT *points = Melder_malloc (POINT, numberOfPoints + close); if (points) { for (long i = 0; i < numberOfPoints; i ++) { points [i]. x = *xyDC, xyDC ++; points [i]. y = *xyDC, xyDC ++; } if (close) points [numberOfPoints] = points [0]; Polyline (our d_gdiGraphicsContext, points, numberOfPoints + close); if (our d_fatNonSolid) { for (long i = 0; i < numberOfPoints; i ++) points [i]. x -= 1; if (close) points [numberOfPoints] = points [0]; Polyline (our d_gdiGraphicsContext, points, numberOfPoints + close); for (long i = 0; i < numberOfPoints; i ++) { points [i]. x += 1; points [i]. y -= 1; } if (close) points [numberOfPoints] = points [0]; Polyline (our d_gdiGraphicsContext, points, numberOfPoints + close); } } DEFAULT #elif mac GraphicsQuartz_initDraw (this); quartzPrepareLine (this); CGContextBeginPath (our d_macGraphicsContext); CGContextMoveToPoint (our d_macGraphicsContext, xyDC [0], xyDC [1]); // starts a new subpath for (long i = 1; i < numberOfPoints; i ++) { CGContextAddLineToPoint (our d_macGraphicsContext, xyDC [i + i], xyDC [i + i + 1]); } if (close) CGContextClosePath (our d_macGraphicsContext); // closes only the subpath CGContextStrokePath (our d_macGraphicsContext); quartzRevertLine (this); GraphicsQuartz_exitDraw (this); #endif }
void draw_render_polygon_object (gerbv_net_t *oldNet, cairo_t *cairoTarget, gdouble sr_x, gdouble sr_y, gerbv_image_t *image, enum draw_mode drawMode, gerbv_selection_info_t *selectionInfo, gboolean pixelOutput) { gerbv_net_t *currentNet, *polygonStartNet; int haveDrawnFirstFillPoint = 0; gdouble x2,y2,cp_x=0,cp_y=0; haveDrawnFirstFillPoint = FALSE; /* save the first net in the polygon as the "ID" net pointer in case we are saving this net to the selection array */ polygonStartNet = oldNet; cairo_new_path(cairoTarget); for (currentNet = oldNet->next; currentNet!=NULL; currentNet = currentNet->next) { x2 = currentNet->stop_x + sr_x; y2 = currentNet->stop_y + sr_y; /* translate circular x,y data as well */ if (currentNet->cirseg) { cp_x = currentNet->cirseg->cp_x + sr_x; cp_y = currentNet->cirseg->cp_y + sr_y; } if (!haveDrawnFirstFillPoint) { draw_cairo_move_to (cairoTarget, x2, y2, FALSE, pixelOutput); haveDrawnFirstFillPoint=TRUE; continue; } switch (currentNet->interpolation) { case GERBV_INTERPOLATION_x10 : case GERBV_INTERPOLATION_LINEARx01 : case GERBV_INTERPOLATION_LINEARx001 : case GERBV_INTERPOLATION_LINEARx1 : draw_cairo_line_to (cairoTarget, x2, y2, FALSE, pixelOutput); break; case GERBV_INTERPOLATION_CW_CIRCULAR : case GERBV_INTERPOLATION_CCW_CIRCULAR : if (currentNet->cirseg->angle2 > currentNet->cirseg->angle1) { cairo_arc (cairoTarget, cp_x, cp_y, currentNet->cirseg->width/2.0, DEG2RAD(currentNet->cirseg->angle1), DEG2RAD(currentNet->cirseg->angle2)); } else { cairo_arc_negative (cairoTarget, cp_x, cp_y, currentNet->cirseg->width/2.0, DEG2RAD(currentNet->cirseg->angle1), DEG2RAD(currentNet->cirseg->angle2)); } break; case GERBV_INTERPOLATION_PAREA_END : cairo_close_path(cairoTarget); /* turn off anti-aliasing for polygons, since it shows seams with adjacent polygons (usually on PCB ground planes) */ cairo_antialias_t oldAlias = cairo_get_antialias (cairoTarget); cairo_set_antialias (cairoTarget, CAIRO_ANTIALIAS_NONE); draw_fill (cairoTarget, drawMode, selectionInfo, image, polygonStartNet); cairo_set_antialias (cairoTarget, oldAlias); return; default : break; } } }
void VectorGraphics::close_path() { cairo_close_path(cr()); }
void ofCairoRenderer::drawPath(const ofShape & path,bool is_subpath){ if(!surface || !cr) return; const vector<ofShape::Command> & commands = path.getCommands(); if(is_subpath) cairo_new_sub_path(cr); else cairo_new_path(cr); for(int i=0; i<(int)commands.size(); i++){ switch(commands[i].type){ case ofShape::Command::lineTo: curvePoints.clear(); cairo_line_to(cr,commands[i].to.x,commands[i].to.y); break; case ofShape::Command::curveTo: curvePoints.push_back(commands[i].to); //code adapted from ofxVectorGraphics to convert catmull rom to bezier if(curvePoints.size()==4){ ofPoint p1=curvePoints[0]; ofPoint p2=curvePoints[1]; ofPoint p3=curvePoints[2]; ofPoint p4=curvePoints[3]; //SUPER WEIRD MAGIC CONSTANT = 1/6 (this works 100% can someone explain it?) ofPoint cp1 = p2 + ( p3 - p1 ) * (1.0/6); ofPoint cp2 = p3 + ( p2 - p4 ) * (1.0/6); cairo_curve_to( cr, cp1.x, cp1.y, cp2.x, cp2.y, p3.x, p3.y ); curvePoints.pop_front(); } break; case ofShape::Command::bezierTo: curvePoints.clear(); cairo_curve_to(cr,commands[i].cp1.x,commands[i].cp1.y,commands[i].cp2.x,commands[i].cp2.y,commands[i].to.x,commands[i].to.y); break; case ofShape::Command::quadBezierTo: curvePoints.clear(); cairo_curve_to(cr,commands[i].cp1.x,commands[i].cp1.y,commands[i].cp2.x,commands[i].cp2.y,commands[i].to.x,commands[i].to.y); break; case ofShape::Command::arc: curvePoints.clear(); // elliptic arcs not directly supported in cairo, lets scale y if(commands[i].radiusX!=commands[i].radiusY){ float ellipse_ratio = commands[i].radiusY/commands[i].radiusX; pushMatrix(); translate(0,-commands[i].to.y*ellipse_ratio); scale(1,ellipse_ratio); translate(0,commands[i].to.y*1/ellipse_ratio); cairo_arc(cr,commands[i].to.x,commands[i].to.y,commands[i].radiusX,commands[i].angleBegin,commands[i].angleEnd); //cairo_set_matrix(cr,&stored_matrix); popMatrix(); }else{ cairo_arc(cr,commands[i].to.x,commands[i].to.y,commands[i].radiusX,commands[i].angleBegin,commands[i].angleEnd); } break; } } if(path.isClosed()){ cairo_close_path(cr); } const vector<ofShape> &subpaths = path.getSubShapes(); for(int i=0;i<(int)subpaths.size();i++){ drawPath(subpaths[i],true); } cairo_fill_rule_t cairo_poly_mode; if(path.getWindingMode()==OF_POLY_WINDING_ODD) cairo_poly_mode=CAIRO_FILL_RULE_EVEN_ODD; else cairo_poly_mode=CAIRO_FILL_RULE_WINDING; cairo_set_fill_rule(cr,cairo_poly_mode); if(path.getStrokeWidth()>0){ ofColor c = path.getStrokeColor() * ofGetStyle().color; c.a = path.getStrokeColor().a/255. * ofGetStyle().color.a; cairo_set_source_rgba(cr, (float)c.r/255.0, (float)c.g/255.0, (float)c.b/255.0, (float)c.a/255.0); cairo_set_line_width( cr, path.getStrokeWidth() ); if(path.isFilled()) cairo_stroke_preserve( cr ); else cairo_stroke( cr ); } if(path.isFilled()){ ofColor c = path.getFillColor() * ofGetStyle().color; c.a = path.getFillColor().a/255. * ofGetStyle().color.a; cairo_set_source_rgba(cr, (float)c.r/255.0, (float)c.g/255.0, (float)c.b/255.0, (float)c.a/255.0); cairo_fill( cr ); } }
void hc_simple_border_gap_clip(cairo_t *canvas, gint border_thickness, gint x, gint y, gint width, gint height, GtkPositionType gap_side, gint gap_pos, gint gap_size) { switch (gap_side) { default: case GTK_POS_TOP: cairo_move_to(canvas, x, y); cairo_line_to(canvas, x, y + height); cairo_line_to(canvas, x + width, y + height); cairo_line_to(canvas, x + width, y); cairo_line_to(canvas, x + gap_pos + gap_size, y); cairo_line_to(canvas, x + gap_pos + gap_size, y + border_thickness + 1); cairo_line_to(canvas, x + gap_pos, y + border_thickness + 1); cairo_line_to(canvas, x + gap_pos, y); cairo_close_path(canvas); break; case GTK_POS_LEFT: cairo_move_to(canvas, x, y); cairo_line_to(canvas, x + width, y); cairo_line_to(canvas, x + width, y + height); cairo_line_to(canvas, x, y + height); cairo_line_to(canvas, x, y + gap_pos + gap_size); cairo_line_to(canvas, x + border_thickness + 1, y + gap_pos + gap_size); cairo_line_to(canvas, x + border_thickness + 1, y + gap_pos); cairo_line_to(canvas, x, y + gap_pos); cairo_close_path(canvas); break; case GTK_POS_BOTTOM: cairo_move_to(canvas, x + width, y + height); cairo_line_to(canvas, x + width, y); cairo_line_to(canvas, x, y); cairo_line_to(canvas, x, y + height); cairo_line_to(canvas, x + gap_pos, y + height); cairo_line_to(canvas, x + gap_pos, y + height - border_thickness - 1); cairo_line_to(canvas, x + gap_pos + gap_size, y + height - border_thickness - 1); cairo_line_to(canvas, x + gap_pos + gap_size, y + height); cairo_close_path(canvas); break; case GTK_POS_RIGHT: cairo_line_to(canvas, x + width, y); cairo_line_to(canvas, x, y); cairo_line_to(canvas, x, y + height); cairo_line_to(canvas, x + width, y + height); cairo_line_to(canvas, x + width, y + gap_pos + gap_size); cairo_line_to(canvas, x + width - border_thickness - 1, y + gap_pos + gap_size); cairo_line_to(canvas, x + width - border_thickness - 1, y + gap_pos); cairo_line_to(canvas, x + width, y + gap_pos); cairo_close_path(canvas); break; } cairo_clip(canvas); }
static void render (GtkWidget * widget) { GSMColorButton *color_button = GSM_COLOR_BUTTON (widget); GdkColor *color, tmp_color = color_button->priv->color; color = &tmp_color; cairo_t *cr = gdk_cairo_create (gtk_widget_get_window (widget)); cairo_path_t *path = NULL; gint width, height; gdouble radius, arc_start, arc_end; gint highlight_factor; if (color_button->priv->highlight > 0) { highlight_factor = 8192 * color_button->priv->highlight; if (color->red + highlight_factor > 65535) color->red = 65535; else color->red = color->red + highlight_factor; if (color->blue + highlight_factor > 65535) color->blue = 65535; else color->blue = color->blue + highlight_factor; if (color->green + highlight_factor > 65535) color->green = 65535; else color->green = color->green + highlight_factor; } gdk_cairo_set_source_color (cr, color); #if GTK_CHECK_VERSION(3, 0, 0) width = gdk_window_get_width(gtk_widget_get_window(widget)); height = gdk_window_get_height(gtk_widget_get_window(widget)); #else gdk_drawable_get_size(gtk_widget_get_window(widget), &width, &height); #endif switch (color_button->priv->type) { case GSMCP_TYPE_CPU: //gtk_widget_set_size_request (widget, GSMCP_MIN_WIDTH, GSMCP_MIN_HEIGHT); cairo_paint (cr); cairo_set_line_width (cr, 1); cairo_set_source_rgba (cr, 0, 0, 0, 0.5); cairo_rectangle (cr, 0.5, 0.5, width - 1, height - 1); cairo_stroke (cr); cairo_set_line_width (cr, 1); cairo_set_source_rgba (cr, 1, 1, 1, 0.4); cairo_rectangle (cr, 1.5, 1.5, width - 3, height - 3); cairo_stroke (cr); break; case GSMCP_TYPE_PIE: if (width < 32) // 32px minimum size gtk_widget_set_size_request (widget, 32, 32); if (width < height) radius = width / 2; else radius = height / 2; arc_start = -G_PI_2 + 2 * G_PI * color_button->priv->fraction; arc_end = -G_PI_2; cairo_set_line_width (cr, 1); // Draw external stroke and fill if (color_button->priv->fraction < 0.01) { cairo_arc (cr, (width / 2) + .5, (height / 2) + .5, 4.5, 0, 2 * G_PI); } else if (color_button->priv->fraction > 0.99) { cairo_arc (cr, (width / 2) + .5, (height / 2) + .5, radius - 2.25, 0, 2 * G_PI); } else { cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, radius - 2.25, arc_start, arc_end); cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, 4.5, arc_end, arc_start); cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, radius - 2.25, arc_start, arc_start); } cairo_fill_preserve (cr); cairo_set_source_rgba (cr, 0, 0, 0, 0.7); cairo_stroke (cr); // Draw internal highlight cairo_set_source_rgba (cr, 1, 1, 1, 0.45); cairo_set_line_width (cr, 1); if (color_button->priv->fraction < 0.03) { cairo_arc (cr, (width / 2) + .5, (height / 2) + .5, 3.25, 0, 2 * G_PI); } else if (color_button->priv->fraction > 0.99) { cairo_arc (cr, (width / 2) + .5, (height / 2) + .5, radius - 3.5, 0, 2 * G_PI); } else { cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, radius - 3.5, arc_start + (1 / (radius - 3.75)), arc_end - (1 / (radius - 3.75))); cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, 3.25, arc_end - (1 / (radius - 3.75)), arc_start + (1 / (radius - 3.75))); cairo_arc_negative (cr, (width / 2) + .5, (height / 2) + .5, radius - 3.5, arc_start + (1 / (radius - 3.75)), arc_start + (1 / (radius - 3.75))); } cairo_stroke (cr); // Draw external shape cairo_set_line_width (cr, 1); cairo_set_source_rgba (cr, 0, 0, 0, 0.2); cairo_arc (cr, (width / 2) + .5, (height / 2) + .5, radius - 1.25, 0, G_PI * 2); cairo_stroke (cr); break; case GSMCP_TYPE_NETWORK_IN: if (color_button->priv->image_buffer == NULL) color_button->priv->image_buffer = fill_image_buffer_from_file (cr, DATADIR "/pixmaps/mate-system-monitor/download.svg"); gtk_widget_set_size_request (widget, 32, 32); cairo_move_to (cr, 8.5, 1.5); cairo_line_to (cr, 23.5, 1.5); cairo_line_to (cr, 23.5, 11.5); cairo_line_to (cr, 29.5, 11.5); cairo_line_to (cr, 16.5, 27.5); cairo_line_to (cr, 15.5, 27.5); cairo_line_to (cr, 2.5, 11.5); cairo_line_to (cr, 8.5, 11.5); cairo_line_to (cr, 8.5, 1.5); cairo_close_path (cr); path = cairo_copy_path (cr); cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER); cairo_set_line_width (cr, 1); cairo_fill_preserve (cr); cairo_set_miter_limit (cr, 5.0); cairo_stroke (cr); cairo_set_source_rgba (cr, 0, 0, 0, 0.5); cairo_append_path (cr, path); cairo_path_destroy(path); cairo_stroke (cr); cairo_set_source_surface (cr, color_button->priv->image_buffer, 0.0, 0.0); cairo_paint (cr); break; case GSMCP_TYPE_NETWORK_OUT: if (color_button->priv->image_buffer == NULL) color_button->priv->image_buffer = fill_image_buffer_from_file (cr, DATADIR "/pixmaps/mate-system-monitor/upload.svg"); gtk_widget_set_size_request (widget, 32, 32); cairo_move_to (cr, 16.5, 1.5); cairo_line_to (cr, 29.5, 17.5); cairo_line_to (cr, 23.5, 17.5); cairo_line_to (cr, 23.5, 27.5); cairo_line_to (cr, 8.5, 27.5); cairo_line_to (cr, 8.5, 17.5); cairo_line_to (cr, 2.5, 17.5); cairo_line_to (cr, 15.5, 1.5); cairo_line_to (cr, 16.5, 1.5); cairo_close_path (cr); path = cairo_copy_path (cr); cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER); cairo_set_line_width (cr, 1); cairo_fill_preserve (cr); cairo_set_miter_limit (cr, 5.0); cairo_stroke (cr); cairo_set_source_rgba (cr, 0, 0, 0, 0.5); cairo_append_path (cr, path); cairo_path_destroy(path); cairo_stroke (cr); cairo_set_source_surface (cr, color_button->priv->image_buffer, 0.0, 0.0); cairo_paint (cr); break; } cairo_destroy (cr); }
static void draw_dvdag_node_1(cairo_t *cr, dv_dag_node_t *node) { // Count node drawn S->nd++; // Node color double x = node->vl->c; double y = node->c; double c[4]; int v = 0; switch (S->nc) { case 0: v = node->pi->info.worker; break; case 1: v = node->pi->info.cpu; break; case 2: v = node->pi->info.kind; break; default: v = node->pi->info.worker; } lookup_color(v, c, c+1, c+2, c+3); // Alpha double alpha = 1.0; // Draw path cairo_save(cr); cairo_new_path(cr); if (dv_is_union(node)) { double xx, yy, w, h; if (dv_is_expanding(node) || dv_is_shrinking(node)) { double margin = 1.0; if (dv_is_expanding(node)) { // Fading out alpha = get_alpha_fading_out(); margin = get_alpha_fading_in(); } else { // Fading in alpha = get_alpha_fading_in(); margin = get_alpha_fading_out(); } // Large-sized box margin *= DV_UNION_NODE_MARGIN; xx = x - node->lc * DV_HDIS - DV_RADIUS - margin; yy = y - DV_RADIUS - margin; dv_dag_node_t * hd = (dv_dag_node_t *) node->heads->top->item; h = hd->dc * DV_VDIS + 2 * (DV_RADIUS + margin); w = (node->lc + node->rc) * DV_HDIS + 2 * (DV_RADIUS + margin); } else { // Normal-sized box xx = x - DV_RADIUS; yy = y - DV_RADIUS; w = 2 * DV_RADIUS; h = 2 * DV_RADIUS; if (node->lv > S->a->new_sel) { // Fading out alpha = get_alpha_fading_out(); } else if (node->lv > S->sel) { // Fading in alpha = get_alpha_fading_in(); } } // Box cairo_move_to(cr, xx, yy); cairo_line_to(cr, xx + w, yy); cairo_line_to(cr, xx + w, yy + h); cairo_line_to(cr, xx, yy + h); cairo_close_path(cr); } else { // Normal-sized circle cairo_arc(cr, x, y, DV_RADIUS, 0.0, 2*M_PI); if (node->lv > S->a->new_sel) { // Fading out alpha = get_alpha_fading_out(); } else if (node->lv > S->sel) { // Fading in alpha = get_alpha_fading_in(); } } // Draw node cairo_set_source_rgba(cr, c[0], c[1], c[2], c[3] * alpha); cairo_fill_preserve(cr); cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, alpha); cairo_stroke(cr); cairo_restore(cr); }
static void img_phase(cairo_t* cr, float scale) { MAKELOCALVARS(scale); const float _rx = 155 * _sc; const float _yl = 95 * _sc; CairoSetSouerceRGBA(c_nrd); cairo_arc (cr, _xc, _yc, _ri+5*_sc, -M_PI/2 - M_PI/4, -M_PI/2 ); cairo_set_line_width (cr, 10*_sc); cairo_stroke (cr); CairoSetSouerceRGBA(c_ngr); cairo_arc (cr, _xc, _yc, _ri+5*_sc, -M_PI/2, -M_PI/2 + M_PI/4 ); cairo_set_line_width (cr, 10*_sc); cairo_stroke (cr); cairo_save(cr); cairo_arc (cr, _xc, _yc, _ri+10*_sc, -M_PI/2 - M_PI/4, -M_PI/2 + M_PI/4 ); cairo_arc_negative (cr, _xc, _yc, _ri, -M_PI/2 + M_PI/4, -M_PI/2 - M_PI/4); cairo_close_path(cr); cairo_clip(cr); #if 1 // S*fam cairo_arc (cr, _xc, _yc, _rs, -M_PI/2 - M_PI/8, -M_PI/2 + M_PI/8 ); cairo_arc_negative (cr, 200*_sc, 129.5*_sc, 80*_sc, -M_PI/2 + M_PI/36 , -M_PI/2 - M_PI/8); cairo_arc_negative(cr, _xc, _yc, _ri, -M_PI/2, -M_PI/2 - M_PI/36); cairo_arc_negative(cr, 99*_sc, 129.5*_sc, 80.5*_sc, -M_PI/2 + M_PI/8 , -M_PI/2 - M_PI/36); CairoSetSouerceRGBA(c_nyl); cairo_fill(cr); #endif cairo_restore(cr); CairoSetSouerceRGBA(c_wht); cairo_arc (cr, _xc, _yc, _ri+10*_sc, -M_PI/2 - M_PI/8, -M_PI/2 + M_PI/8 ); cairo_set_line_width (cr, .5 * _sc); cairo_stroke (cr); cairo_arc (cr, _xc, _yc, _ri, -M_PI/2 - M_PI/4, -M_PI/2 + M_PI/4 ); cairo_set_line_width (cr, 1 * _sc); cairo_stroke (cr); int v; for (v = 0; v <= 20 ; v++) { if (v == 0 || v == 5 || v == 10 || v == 15 || v == 20) { continue; } else { img_draw_needle(cr, v/20.0, _ri, _rs, c_wsh, 1.0); } } img_draw_needle(cr, 0.0, _rx, _rl-5, c_wht, 1.5); img_draw_needle(cr, 0.25, _rx, _rl-5, c_wht, 1.5); img_draw_needle(cr, 0.5, _rx, _rl-5, c_wht, 1.5); img_draw_needle(cr, 0.75, _rx, _rl-5, c_wht, 1.5); img_draw_needle(cr, 1.0, _rx, _rl-5, c_wht, 1.5); sprintf(img_fontname, "Sans Bold %dpx", (int)rint(_rl/20)); img_needle_label(cr, "-1", 0, _rs-24*_sc); img_needle_label(cr, "-0.5", .25, _rs-24*_sc); img_needle_label(cr, "0", 0.5, _rs-24*_sc); img_needle_label(cr, "+0.5", .75, _rs-24*_sc); img_needle_label(cr, "+1", 1.0, _rs-24*_sc); img_needle_label(cr," 180\u00B0\n", 0, _rl); img_needle_label(cr, " 135\u00B0\n", .25, _rl); img_needle_label(cr, " 90\u00B0\n", 0.5, _rl); img_needle_label(cr, " 45\u00B0\n", .75, _rl); img_needle_label(cr, " 0\u00B0\n", 1.0, _rl); CairoSetSouerceRGBA(c_wht); img_write_text(cr, "Corr", img_fonthuge, _xc + .5, _yl, 0); }
/*! \brief Actually renders the swatch */ static void ghid_cell_renderer_visibility_render (GtkCellRenderer *cell, GdkWindow *window, GtkWidget *widget, GdkRectangle *background_area, GdkRectangle *cell_area, GdkRectangle *expose_area, GtkCellRendererState flags) { GHidCellRendererVisibility *pcb_cell; GdkRectangle toggle_rect; GdkRectangle draw_rect; gint xpad, ypad; pcb_cell = GHID_CELL_RENDERER_VISIBILITY (cell); ghid_cell_renderer_visibility_get_size (cell, widget, cell_area, &toggle_rect.x, &toggle_rect.y, &toggle_rect.width, &toggle_rect.height); gtk_cell_renderer_get_padding (cell, &xpad, &ypad); toggle_rect.x += cell_area->x + xpad; toggle_rect.y += cell_area->y + ypad; toggle_rect.width -= xpad * 2; toggle_rect.height -= ypad * 2; if (toggle_rect.width <= 0 || toggle_rect.height <= 0) return; if (gdk_rectangle_intersect (expose_area, cell_area, &draw_rect)) { GdkColor color; cairo_t *cr = gdk_cairo_create (window); cairo_pattern_t *pattern; if (expose_area) { gdk_cairo_rectangle (cr, expose_area); cairo_clip (cr); } cairo_set_line_width (cr, 1); cairo_rectangle (cr, toggle_rect.x + 0.5, toggle_rect.y + 0.5, toggle_rect.width - 1, toggle_rect.height - 1); cairo_set_source_rgb (cr, 1, 1, 1); cairo_fill_preserve (cr); cairo_set_source_rgb (cr, 0, 0, 0); cairo_stroke (cr); gdk_color_parse (pcb_cell->color, &color); if (flags & GTK_CELL_RENDERER_PRELIT) { color.red = (4*color.red + 65535) / 5; color.green = (4*color.green + 65535) / 5; color.blue = (4*color.blue + 65535) / 5; } pattern = cairo_pattern_create_radial ((toggle_rect.width - 1.) * 0.75 + toggle_rect.x + 0.5, (toggle_rect.height - 1.) * 0.75 + toggle_rect.y + 0.5, 0., (toggle_rect.width - 1.) * 0.50 + toggle_rect.x + 0.5, (toggle_rect.height - 1.) * 0.50 + toggle_rect.y + 0.5, (toggle_rect.width - 1.) * 0.71); cairo_pattern_add_color_stop_rgb (pattern, 0.0, (color.red / 65535. * 4. + 1.) / 5., (color.green / 65535. * 4. + 1.) / 5., (color.blue / 65535. * 4. + 1.) / 5.); cairo_pattern_add_color_stop_rgb (pattern, 1.0, (color.red / 65535. * 5. + 0.) / 5., (color.green / 65535. * 5. + 0.) / 5., (color.blue / 65535. * 5. + 0.) / 5.); cairo_set_source (cr, pattern); cairo_pattern_destroy (pattern); if (pcb_cell->active) cairo_rectangle (cr, toggle_rect.x + 0.5, toggle_rect.y + 0.5, toggle_rect.width - 1, toggle_rect.height - 1); else { cairo_move_to (cr, toggle_rect.x + 1, toggle_rect.y + 1); cairo_rel_line_to (cr, toggle_rect.width / 2, 0); cairo_rel_line_to (cr, -toggle_rect.width / 2, toggle_rect.width / 2); cairo_close_path (cr); } cairo_fill (cr); cairo_destroy (cr); } }
static gboolean dt_iop_levels_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { dt_iop_module_t *self = (dt_iop_module_t *)user_data; dt_iop_levels_gui_data_t *c = (dt_iop_levels_gui_data_t *)self->gui_data; dt_iop_levels_params_t *p = (dt_iop_levels_params_t *)self->params; const int inset = DT_GUI_CURVE_EDITOR_INSET; int width = widget->allocation.width, height = widget->allocation.height; cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); float mean_picked_color = *self->picked_color / 100.0; /* we need to save the last picked color to prevent flickering when * changing from one picker to another, as the picked_color value does not * update as rapidly */ if(self->request_color_pick && self->color_picker_point[0] >= 0.0f && self->color_picker_point[1] >= 0.0f && mean_picked_color != c->last_picked_color) { float previous_color[3]; previous_color[0] = p->levels[0]; previous_color[1] = p->levels[1]; previous_color[2] = p->levels[2]; c->last_picked_color = mean_picked_color; if (BLACK == c->current_pick) { if (mean_picked_color > p->levels[1]) { p->levels[0] = p->levels[1]-FLT_EPSILON; } else { p->levels[0] = mean_picked_color; } c->pick_xy_positions[0][0] = self->color_picker_point[0]; c->pick_xy_positions[0][1] = self->color_picker_point[1]; } else if (GREY == c->current_pick) { if (mean_picked_color < p->levels[0] || mean_picked_color > p->levels[2]) { p->levels[1] = p->levels[1]; } else { p->levels[1] = mean_picked_color; } c->pick_xy_positions[1][0] = self->color_picker_point[0]; c->pick_xy_positions[1][1] = self->color_picker_point[1]; } else if (WHITE == c->current_pick) { if (mean_picked_color < p->levels[1]) { p->levels[2] = p->levels[1]+FLT_EPSILON; } else { p->levels[2] = mean_picked_color; } c->pick_xy_positions[2][0] = self->color_picker_point[0]; c->pick_xy_positions[2][1] = self->color_picker_point[1]; } if ( previous_color[0] != p->levels[0] || previous_color[1] != p->levels[1] || previous_color[2] != p->levels[2] ) { dt_dev_add_history_item(darktable.develop, self, TRUE); } } // clear bg cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); cairo_translate(cr, inset, inset); width -= 2*inset; height -= 2*inset; cairo_set_line_width(cr, 1.0); cairo_set_source_rgb (cr, .1, .1, .1); cairo_rectangle(cr, 0, 0, width, height); cairo_stroke(cr); cairo_set_source_rgb (cr, .3, .3, .3); cairo_rectangle(cr, 0, 0, width, height); cairo_fill(cr); // draw grid cairo_set_line_width(cr, .4); cairo_set_source_rgb (cr, .1, .1, .1); dt_draw_vertical_lines(cr, 4, 0, 0, width, height); // Drawing the vertical line indicators cairo_set_line_width(cr, 2.); for(int k = 0; k < 3; k++) { if(k == c->handle_move && c->mouse_x > 0) cairo_set_source_rgb(cr, 1, 1, 1); else cairo_set_source_rgb(cr, .7, .7, .7); cairo_move_to(cr, width*p->levels[k], height); cairo_rel_line_to(cr, 0, -height); cairo_stroke(cr); } // draw x positions cairo_set_line_width(cr, 1.); const float arrw = 7.0f; for(int k=0; k<3; k++) { switch(k) { case 0: cairo_set_source_rgb(cr, 0, 0, 0); break; case 1: cairo_set_source_rgb(cr, 0.5, 0.5, 0.5); break; default: cairo_set_source_rgb(cr, 1, 1, 1); break; } cairo_move_to(cr, width*p->levels[k], height+inset-1); cairo_rel_line_to(cr, -arrw*.5f, 0); cairo_rel_line_to(cr, arrw*.5f, -arrw); cairo_rel_line_to(cr, arrw*.5f, arrw); cairo_close_path(cr); if(c->handle_move == k && c->mouse_x > 0) cairo_fill(cr); else cairo_stroke(cr); } cairo_translate(cr, 0, height); // draw lum histogram in background // only if the module is enabled if (self->enabled) { dt_develop_t *dev = darktable.develop; float *hist, hist_max; hist = self->histogram; hist_max = dev->histogram_linear?self->histogram_max[0]:logf(1.0 + self->histogram_max[0]); if(hist && hist_max > 0) { cairo_save(cr); cairo_scale(cr, width/63.0, -(height-5)/(float)hist_max); cairo_set_source_rgba(cr, .2, .2, .2, 0.5); dt_draw_histogram_8(cr, hist, 0); cairo_restore(cr); } } // Cleaning up cairo_destroy(cr); cairo_t *cr_pixmap = gdk_cairo_create(gtk_widget_get_window(widget)); cairo_set_source_surface (cr_pixmap, cst, 0, 0); cairo_paint(cr_pixmap); cairo_destroy(cr_pixmap); cairo_surface_destroy(cst); return TRUE; }
static cairo_time_t draw_spiral (cairo_t *cr, cairo_fill_rule_t fill_rule, align_t align, close_t close, int width, int height, int loops) { int i; int n=0; double x[MAX_SEGMENTS]; double y[MAX_SEGMENTS]; int step = 3; int side = width < height ? width : height; assert(5*(side/step/2+1)+2 < MAX_SEGMENTS); #define L(x_,y_) (x[n] = (x_), y[n] = (y_), n++) #define M(x_,y_) L(x_,y_) #define v(t) L(x[n-1], y[n-1] + (t)) #define h(t) L(x[n-1] + (t), y[n-1]) switch (align) { case PIXALIGN: M(0,0); break; case NONALIGN: M(0.1415926, 0.7182818); break; } while (side >= step && side >= 0) { v(side); h(side); v(-side); h(-side+step); v(step); side -= 2*step; } switch (close) { case RECTCLOSE: L(x[n-1],y[0]); break; case DIAGCLOSE: L(x[0],y[0]); break; } assert(n < MAX_SEGMENTS); cairo_save (cr); cairo_set_source_rgb (cr, 0, 0, 0); cairo_paint (cr); cairo_translate (cr, 1, 1); cairo_set_fill_rule (cr, fill_rule); cairo_set_source_rgb (cr, 1, 0, 0); cairo_new_path (cr); cairo_move_to (cr, x[0], y[0]); for (i = 1; i < n; i++) { cairo_line_to (cr, x[i], y[i]); } cairo_close_path (cr); cairo_perf_timer_start (); cairo_perf_set_thread_aware (cr, FALSE); while (loops--) { if (loops == 0) cairo_perf_set_thread_aware (cr, TRUE); cairo_fill_preserve (cr); } cairo_perf_timer_stop (); cairo_restore (cr); return cairo_perf_timer_elapsed (); }
/* * BackgroundLayer::render * * Render the background to the tab bar, also render the tab bar animation * */ void BackgroundLayer::render () { cairo_t *cr; int twidth, theight, radius; int borderWidth; float r, g, b, a; double x0, y0, x1, y1; GROUP_SCREEN (screen); if (!HAS_TOP_WIN (mGroup) || !mCairo) return; /* Dimensions are the tab bar's region */ twidth = mGroup->mTabBar->mRegion.boundingRect ().width (); theight = mGroup->mTabBar->mRegion.boundingRect ().height (); radius = gs->optionGetBorderRadius (); /* Do not draw more than the tab bar width */ if (twidth > width ()) twidth = width (); /* Border radius should not exceed * half of the tab bar height */ if (radius > twidth / 2) radius = twidth / 2; cr = mCairo; /* Clear the layer */ clear (); /* Draw the border around the tab bar */ borderWidth = gs->optionGetBorderWidth (); cairo_set_line_width (cr, borderWidth); cairo_save (cr); /* Move to the center of where we want to draw the line */ x0 = borderWidth / 2.0f; y0 = borderWidth / 2.0f; /* The center of where we want to draw the opposite line */ x1 = twidth - borderWidth / 2.0f; y1 = theight - borderWidth / 2.0f; cairo_move_to (cr, x0 + radius, y0); /* Arc the top right corner */ cairo_arc (cr, x1 - radius, y0 + radius, radius, M_PI * 1.5, M_PI * 2.0); /* Arc the bottom right corner */ cairo_arc (cr, x1 - radius, y1 - radius, radius, 0.0, M_PI * 0.5); /* Arc the bottom left corner */ cairo_arc (cr, x0 + radius, y1 - radius, radius, M_PI * 0.5, M_PI); /* Arc the top left corner */ cairo_arc (cr, x0 + radius, y0 + radius, radius, M_PI, M_PI * 1.5); cairo_close_path (cr); /* There are 5 different tab styles here: * Simple: draws a simple filled rect * Gradient: left to right gradient between base and highlight * Glass: left to right gradient, stopping at 60% and drawing a shadow * Metal: base -> highlight -> base gradient * Murrina: draws an arc between the two corners blending base and highlight */ switch (gs->optionGetTabStyle ()) { case GroupOptions::TabStyleSimple: { /* base color */ r = gs->optionGetTabBaseColorRed () / 65535.0f; g = gs->optionGetTabBaseColorGreen () / 65535.0f; b = gs->optionGetTabBaseColorBlue () / 65535.0f; a = gs->optionGetTabBaseColorAlpha () / 65535.0f; cairo_set_source_rgba (cr, r, g, b, a); cairo_fill_preserve (cr); break; } case GroupOptions::TabStyleGradient: { /* fill */ cairo_pattern_t *pattern; pattern = cairo_pattern_create_linear (0, 0, twidth, theight); /* highlight color */ r = gs->optionGetTabHighlightColorRed () / 65535.0f; g = gs->optionGetTabHighlightColorGreen () / 65535.0f; b = gs->optionGetTabHighlightColorBlue () / 65535.0f; a = gs->optionGetTabHighlightColorAlpha () / 65535.0f; cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a); /* base color */ r = gs->optionGetTabBaseColorRed () / 65535.0f; g = gs->optionGetTabBaseColorGreen () / 65535.0f; b = gs->optionGetTabBaseColorBlue () / 65535.0f; a = gs->optionGetTabBaseColorAlpha () / 65535.0f; cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a); cairo_set_source (cr, pattern); cairo_fill_preserve (cr); cairo_pattern_destroy (pattern); break; } case GroupOptions::TabStyleGlass: { cairo_pattern_t *pattern; cairo_save (cr); /* clip width rounded rectangle */ cairo_clip (cr); /* ===== HIGHLIGHT ===== */ /* make draw the shape for the highlight and create a pattern for it */ cairo_rectangle (cr, 0, 0, twidth, theight / 2); pattern = cairo_pattern_create_linear (0, 0, 0, theight); /* highlight color */ r = gs->optionGetTabHighlightColorRed () / 65535.0f; g = gs->optionGetTabHighlightColorGreen () / 65535.0f; b = gs->optionGetTabHighlightColorBlue () / 65535.0f; a = gs->optionGetTabHighlightColorAlpha () / 65535.0f; cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a); /* base color */ r = gs->optionGetTabBaseColorRed () / 65535.0f; g = gs->optionGetTabBaseColorGreen () / 65535.0f; b = gs->optionGetTabBaseColorBlue () / 65535.0f; a = gs->optionGetTabBaseColorAlpha () / 65535.0f; cairo_pattern_add_color_stop_rgba (pattern, 0.6f, r, g, b, a); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); /* ==== SHADOW ===== */ /* make draw the shape for the show and create a pattern for it */ cairo_rectangle (cr, 0, theight / 2, twidth, theight); pattern = cairo_pattern_create_linear (0, 0, 0, theight); /* we don't want to use a full highlight here so we mix the colors */ r = (gs->optionGetTabHighlightColorRed () + gs->optionGetTabBaseColorRed ()) / (2 * 65535.0f); g = (gs->optionGetTabHighlightColorGreen () + gs->optionGetTabBaseColorGreen ()) / (2 * 65535.0f); b = (gs->optionGetTabHighlightColorBlue () + gs->optionGetTabBaseColorBlue ()) / (2 * 65535.0f); a = (gs->optionGetTabHighlightColorAlpha () + gs->optionGetTabBaseColorAlpha ()) / (2 * 65535.0f); cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a); /* base color */ r = gs->optionGetTabBaseColorRed () / 65535.0f; g = gs->optionGetTabBaseColorGreen () / 65535.0f; b = gs->optionGetTabBaseColorBlue () / 65535.0f; a = gs->optionGetTabBaseColorAlpha () / 65535.0f; cairo_pattern_add_color_stop_rgba (pattern, 0.5f, r, g, b, a); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); cairo_restore (cr); /* draw shape again for the outline */ cairo_move_to (cr, x0 + radius, y0); cairo_arc (cr, x1 - radius, y0 + radius, radius, M_PI * 1.5, M_PI * 2.0); cairo_arc (cr, x1 - radius, y1 - radius, radius, 0.0, M_PI * 0.5); cairo_arc (cr, x0 + radius, y1 - radius, radius, M_PI * 0.5, M_PI); cairo_arc (cr, x0 + radius, y0 + radius, radius, M_PI, M_PI * 1.5); break; } case GroupOptions::TabStyleMetal: { /* fill */ cairo_pattern_t *pattern; pattern = cairo_pattern_create_linear (0, 0, 0, theight); /* base color #1 */ r = gs->optionGetTabBaseColorRed () / 65535.0f; g = gs->optionGetTabBaseColorGreen () / 65535.0f; b = gs->optionGetTabBaseColorBlue () / 65535.0f; a = gs->optionGetTabBaseColorAlpha () / 65535.0f; cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a); /* highlight color */ r = gs->optionGetTabHighlightColorRed () / 65535.0f; g = gs->optionGetTabHighlightColorGreen () / 65535.0f; b = gs->optionGetTabHighlightColorBlue () / 65535.0f; a = gs->optionGetTabHighlightColorAlpha () / 65535.0f; cairo_pattern_add_color_stop_rgba (pattern, 0.55f, r, g, b, a); /* base color #2 */ r = gs->optionGetTabBaseColorRed () / 65535.0f; g = gs->optionGetTabBaseColorGreen () / 65535.0f; b = gs->optionGetTabBaseColorBlue () / 65535.0f; a = gs->optionGetTabBaseColorAlpha () / 65535.0f; cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a); cairo_set_source (cr, pattern); cairo_fill_preserve (cr); cairo_pattern_destroy (pattern); break; } case GroupOptions::TabStyleMurrina: { double ratio, transX; cairo_pattern_t *pattern; cairo_save (cr); /* clip width rounded rectangle */ cairo_clip_preserve (cr); /* ==== TOP ==== */ x0 = borderWidth / 2.0; y0 = borderWidth / 2.0; x1 = twidth - borderWidth / 2.0; y1 = theight - borderWidth / 2.0; radius = (y1 - y0) / 2; /* setup pattern */ pattern = cairo_pattern_create_linear (0, 0, 0, theight); /* we don't want to use a full highlight here so we mix the colors */ r = (gs->optionGetTabHighlightColorRed () + gs->optionGetTabBaseColorRed ()) / (2 * 65535.0f); g = (gs->optionGetTabHighlightColorGreen () + gs->optionGetTabBaseColorGreen ()) / (2 * 65535.0f); b = (gs->optionGetTabHighlightColorBlue () + gs->optionGetTabBaseColorBlue ()) / (2 * 65535.0f); a = (gs->optionGetTabHighlightColorAlpha () + gs->optionGetTabBaseColorAlpha ()) / (2 * 65535.0f); cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a); /* highlight color */ r = gs->optionGetTabHighlightColorRed () / 65535.0f; g = gs->optionGetTabHighlightColorGreen () / 65535.0f; b = gs->optionGetTabHighlightColorBlue () / 65535.0f; a = gs->optionGetTabHighlightColorAlpha () / 65535.0f; cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); /* ==== BOTTOM ===== */ x0 = borderWidth / 2.0; y0 = borderWidth / 2.0; x1 = twidth - borderWidth / 2.0; y1 = theight - borderWidth / 2.0; radius = (y1 - y0) / 2; ratio = (double)twidth / (double)theight; transX = twidth - (twidth * ratio); cairo_move_to (cr, x1, y1); cairo_line_to (cr, x1, y0); if (twidth < theight) { cairo_translate (cr, transX, 0); cairo_scale (cr, ratio, 1.0); } cairo_arc (cr, x1 - radius, y0, radius, 0.0, M_PI * 0.5); if (twidth < theight) { cairo_scale (cr, 1.0 / ratio, 1.0); cairo_translate (cr, -transX, 0); cairo_scale (cr, ratio, 1.0); } cairo_arc_negative (cr, x0 + radius, y1, radius, M_PI * 1.5, M_PI); cairo_close_path (cr); /* setup pattern */ pattern = cairo_pattern_create_linear (0, 0, 0, theight); /* base color */ r = gs->optionGetTabBaseColorRed () / 65535.0f; g = gs->optionGetTabBaseColorGreen () / 65535.0f; b = gs->optionGetTabBaseColorBlue () / 65535.0f; a = gs->optionGetTabBaseColorAlpha () / 65535.0f; cairo_pattern_add_color_stop_rgba (pattern, 0.0f, r, g, b, a); /* we don't want to use a full highlight here so we mix the colors */ r = (gs->optionGetTabHighlightColorRed () + gs->optionGetTabBaseColorRed ()) / (2 * 65535.0f); g = (gs->optionGetTabHighlightColorGreen () + gs->optionGetTabBaseColorGreen ()) / (2 * 65535.0f); b = (gs->optionGetTabHighlightColorBlue () + gs->optionGetTabBaseColorBlue ()) / (2 * 65535.0f); a = (gs->optionGetTabHighlightColorAlpha () + gs->optionGetTabBaseColorAlpha ()) / (2 * 65535.0f); cairo_pattern_add_color_stop_rgba (pattern, 1.0f, r, g, b, a); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_restore (cr); /* draw shape again for the outline */ x0 = borderWidth / 2.0; y0 = borderWidth / 2.0; x1 = twidth - borderWidth / 2.0; y1 = theight - borderWidth / 2.0; radius = gs->optionGetBorderRadius (); cairo_move_to (cr, x0 + radius, y0); cairo_arc (cr, x1 - radius, y0 + radius, radius, M_PI * 1.5, M_PI * 2.0); cairo_arc (cr, x1 - radius, y1 - radius, radius, 0.0, M_PI * 0.5); cairo_arc (cr, x0 + radius, y1 - radius, radius, M_PI * 0.5, M_PI); cairo_arc (cr, x0 + radius, y0 + radius, radius, M_PI, M_PI * 1.5); break; } default: break; } /* outline */ r = gs->optionGetTabBorderColorRed () / 65535.0f; g = gs->optionGetTabBorderColorGreen () / 65535.0f; b = gs->optionGetTabBorderColorBlue () / 65535.0f; a = gs->optionGetTabBorderColorAlpha () / 65535.0f; cairo_set_source_rgba (cr, r, g, b, a); /* If there is an animation running, stroke preserved * so that we can paint directly on top (and blend!) * the new animation with the existing tab bar. * Otherwise just stroke normally, this is less expensive */ if (mBgAnimation != AnimationNone) cairo_stroke_preserve (cr); else cairo_stroke (cr); /* There are two animations here: * Pulse: Highlight tab bar in and out (used for tab hover) * Reflex: Paint a diagonal gradient moving from right to left * on the tab bar when it appears */ switch (mBgAnimation) { case AnimationPulse: { double animationProgress; double alpha; /* Progress here is measured in the current time */ animationProgress = mBgAnimationTime / (gs->optionGetPulseTime () * 1000.0); /* The highlight pulsates in and out, so the alpha here should run * on a sine wave */ alpha = sin ((2 * PI * animationProgress) - 1.55)*0.5 + 0.5; /* If the alpha of the animation is < 0, don't bother painting */ if (alpha <= 0) break; cairo_save (cr); cairo_clip (cr); /* Paint highlight over the tab bar */ cairo_set_operator (cr, CAIRO_OPERATOR_XOR); cairo_rectangle (cr, 0.0, 0.0, twidth, theight); cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, alpha); cairo_fill (cr); cairo_restore (cr); break; } case AnimationReflex: { double animationProgress; double reflexWidth; double posX, alpha; cairo_pattern_t *pattern; /* Progress is measured in current time */ animationProgress = mBgAnimationTime / (gs->optionGetReflexTime () * 1000.0); /* Position here is the tab bar width plus the reflection width * 2 */ reflexWidth = (mGroup->mTabBar->mSlots.size () / 2.0) * 30; posX = (twidth + reflexWidth * 2.0) * animationProgress; alpha = sin (PI * animationProgress) * 0.55; if (alpha <= 0) break; cairo_save (cr); cairo_clip (cr); pattern = cairo_pattern_create_linear (posX - reflexWidth, 0.0, posX, theight); cairo_pattern_add_color_stop_rgba (pattern, 0.0f, 1.0, 1.0, 1.0, 0.0); cairo_pattern_add_color_stop_rgba (pattern, 0.5f, 1.0, 1.0, 1.0, alpha); cairo_pattern_add_color_stop_rgba (pattern, 1.0f, 1.0, 1.0, 1.0, 0.0); cairo_rectangle (cr, 0.0, 0.0, twidth, theight); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_restore (cr); cairo_pattern_destroy (pattern); break; } case AnimationNone: default: break; } /* draw inner outline */ cairo_move_to (cr, x0 + radius + 1.0, y0 + 1.0); cairo_arc (cr, x1 - radius - 1.0, y0 + radius + 1.0, radius, M_PI * 1.5, M_PI * 2.0); cairo_arc (cr, x1 - radius - 1.0, y1 - radius - 1.0, radius, 0.0, M_PI * 0.5); cairo_arc (cr, x0 + radius + 1.0, y1 - radius - 1.0, radius, M_PI * 0.5, M_PI); cairo_arc (cr, x0 + radius + 1.0, y0 + radius + 1.0, radius, M_PI, M_PI * 1.5); cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.3); cairo_stroke(cr); cairo_restore (cr); mTexture = GLTexture::imageBufferToTexture ((char*) mBuffer, (CompSize &) *this); }
/* * Draws global image with fill color onto a pixmap with the given * resolution and returns it. * */ xcb_pixmap_t draw_image(uint32_t *resolution) { xcb_pixmap_t bg_pixmap = XCB_NONE; int button_diameter_physical = ceil(scaling_factor() * BUTTON_DIAMETER); DEBUG("scaling_factor is %.f, physical diameter is %d px\n", scaling_factor(), button_diameter_physical); if (!vistype) vistype = get_root_visual_type(screen); bg_pixmap = create_bg_pixmap(conn, screen, resolution, color); /* Initialize cairo: Create one in-memory surface to render the unlock * indicator on, create one XCB surface to actually draw (one or more, * depending on the amount of screens) unlock indicators on. */ cairo_surface_t *output = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, button_diameter_physical, button_diameter_physical); cairo_t *ctx = cairo_create(output); cairo_t *ctx1 = cairo_create(output); cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, bg_pixmap, vistype, resolution[0], resolution[1]); cairo_t *xcb_ctx = cairo_create(xcb_output); cairo_text_extents_t extents; double x, y; cairo_set_source_rgb(ctx1, 0, 0, 0); cairo_set_font_size(ctx1, 12.0); cairo_text_extents(ctx1, flg_string, &extents); x = BUTTON_CENTER - ((extents.width / 2) + extents.x_bearing) - 12; y = BUTTON_CENTER - ((extents.height / 2) + extents.y_bearing) + 75 ; cairo_move_to(ctx1, x, y); cairo_show_text(ctx1, flg_string); cairo_close_path(ctx1); if (img) { if (!tile) { cairo_set_source_surface(xcb_ctx, img, 0, 0); cairo_paint(xcb_ctx); } else { /* create a pattern and fill a rectangle as big as the screen */ cairo_pattern_t *pattern; pattern = cairo_pattern_create_for_surface(img); cairo_set_source(xcb_ctx, pattern); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]); cairo_fill(xcb_ctx); cairo_pattern_destroy(pattern); } } else { char strgroups[3][3] = {{color[0], color[1], '\0'}, {color[2], color[3], '\0'}, {color[4], color[5], '\0'}}; uint32_t rgb16[3] = {(strtol(strgroups[0], NULL, 16)), (strtol(strgroups[1], NULL, 16)), (strtol(strgroups[2], NULL, 16))}; cairo_set_source_rgb(xcb_ctx, rgb16[0] / 255.0, rgb16[1] / 255.0, rgb16[2] / 255.0); cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]); cairo_fill(xcb_ctx); } if (unlock_state >= STATE_KEY_PRESSED && unlock_indicator) { cairo_scale(ctx, scaling_factor(), scaling_factor()); /* Draw a (centered) circle with transparent background. */ cairo_set_line_width(ctx, 10.0); cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, 0 /* start */, 2 * M_PI /* end */); /* Use the appropriate color for the different PAM states * (currently verifying, wrong password, or default) */ switch (pam_state) { case STATE_PAM_VERIFY: cairo_set_source_rgba(ctx, 0, 114.0/255, 255.0/255, 0.75); break; case STATE_PAM_WRONG: cairo_set_source_rgba(ctx, 250.0/255, 0, 0, 0.75); break; default: cairo_set_source_rgba(ctx, 0, 0, 0, 0.75); break; } cairo_fill_preserve(ctx); switch (pam_state) { case STATE_PAM_VERIFY: cairo_set_source_rgb(ctx, 51.0/255, 0, 250.0/255); break; case STATE_PAM_WRONG: cairo_set_source_rgb(ctx, 125.0/255, 51.0/255, 0); break; case STATE_PAM_IDLE: cairo_set_source_rgb(ctx, 51.0/255, 125.0/255, 0); break; } cairo_stroke(ctx); /* Draw an inner seperator line. */ cairo_set_source_rgb(ctx, 0, 0, 0); cairo_set_line_width(ctx, 2.0); cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS - 5 /* radius */, 0, 2 * M_PI); cairo_stroke(ctx); cairo_set_line_width(ctx, 10.0); /* Display a (centered) text of the current PAM state. */ char *text = NULL; switch (pam_state) { case STATE_PAM_VERIFY: text = "verifying…"; break; case STATE_PAM_WRONG: text = "wrong!"; break; default: break; } if (text) { cairo_text_extents_t extents; double x, y; cairo_set_source_rgb(ctx, 0, 0, 0); cairo_set_font_size(ctx, 28.0); cairo_text_extents(ctx, text, &extents); x = BUTTON_CENTER - ((extents.width / 2) + extents.x_bearing); y = BUTTON_CENTER - ((extents.height / 2) + extents.y_bearing); cairo_move_to(ctx, x, y); cairo_show_text(ctx, text); cairo_close_path(ctx); } /* After the user pressed any valid key or the backspace key, we * highlight a random part of the unlock indicator to confirm this * keypress. */ if (unlock_state == STATE_KEY_ACTIVE || unlock_state == STATE_BACKSPACE_ACTIVE) { cairo_new_sub_path(ctx); double highlight_start = (rand() % (int)(2 * M_PI * 100)) / 100.0; cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, highlight_start, highlight_start + (M_PI / 3.0)); if (unlock_state == STATE_KEY_ACTIVE) { /* For normal keys, we use a lighter green. */ cairo_set_source_rgb(ctx, 51.0/255, 219.0/255, 0); } else { /* For backspace, we use red. */ cairo_set_source_rgb(ctx, 219.0/255, 51.0/255, 0); } cairo_stroke(ctx); /* Draw two little separators for the highlighted part of the * unlock indicator. */ cairo_set_source_rgb(ctx, 0, 0, 0); cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, highlight_start /* start */, highlight_start + (M_PI / 128.0) /* end */); cairo_stroke(ctx); cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, highlight_start + (M_PI / 3.0) /* start */, (highlight_start + (M_PI / 3.0)) + (M_PI / 128.0) /* end */); cairo_stroke(ctx); } } if (xr_screens > 0) { /* Composite the unlock indicator in the middle of each screen. */ for (int screen = 0; screen < xr_screens; screen++) { int x = (xr_resolutions[screen].x + ((xr_resolutions[screen].width / 2) - (button_diameter_physical / 2))); int y = (xr_resolutions[screen].y + ((xr_resolutions[screen].height / 2) - (button_diameter_physical / 2))); cairo_set_source_surface(xcb_ctx, output, x, y); cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical); cairo_fill(xcb_ctx); } } else { /* We have no information about the screen sizes/positions, so we just * place the unlock indicator in the middle of the X root window and * hope for the best. */ int x = (last_resolution[0] / 2) - (button_diameter_physical / 2); int y = (last_resolution[1] / 2) - (button_diameter_physical / 2); cairo_set_source_surface(xcb_ctx, output, x, y); cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical); cairo_fill(xcb_ctx); } cairo_surface_destroy(xcb_output); cairo_surface_destroy(output); cairo_destroy(ctx); cairo_destroy(xcb_ctx); return bg_pixmap; }
static void draw_text_bubble (cairo_t *cr, GtkWidget *widget, gdouble pointx, gdouble pointy) { static const double corner_radius = 9.0; static const double margin_top = 12.0; static const double margin_bottom = 12.0; static const double margin_left = 24.0; static const double margin_right = 24.0; CcTimezoneMapPrivate *priv = CC_TIMEZONE_MAP (widget)->priv; GtkAllocation alloc; PangoLayout *layout; PangoRectangle text_rect; double x; double y; double width; double height; if (!priv->bubble_text) return; gtk_widget_get_allocation (widget, &alloc); layout = gtk_widget_create_pango_layout (widget, NULL); /* Layout the text */ pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); pango_layout_set_spacing (layout, 3); pango_layout_set_markup (layout, priv->bubble_text, -1); pango_layout_get_pixel_extents (layout, NULL, &text_rect); /* Calculate the bubble size based on the text layout size */ width = text_rect.width + margin_left + margin_right; height = text_rect.height + margin_top + margin_bottom; if (pointx < alloc.width / 2) x = pointx + 25; else x = pointx - width - 25; y = pointy - height / 2; /* Make sure it fits in the visible area */ x = CLAMP (x, 0, alloc.width - width); y = CLAMP (y, 0, alloc.height - height); cairo_save (cr); cairo_translate (cr, x, y); /* Draw the bubble */ cairo_new_sub_path (cr); cairo_arc (cr, width - corner_radius, corner_radius, corner_radius, radians (-90), radians (0)); cairo_arc (cr, width - corner_radius, height - corner_radius, corner_radius, radians (0), radians (90)); cairo_arc (cr, corner_radius, height - corner_radius, corner_radius, radians (90), radians (180)); cairo_arc (cr, corner_radius, corner_radius, corner_radius, radians (180), radians (270)); cairo_close_path (cr); cairo_set_source_rgba (cr, 0.2, 0.2, 0.2, 0.7); cairo_fill (cr); /* And finally draw the text */ cairo_set_source_rgb (cr, 1, 1, 1); cairo_move_to (cr, margin_left, margin_top); pango_cairo_show_layout (cr, layout); g_object_unref (layout); cairo_restore (cr); }
static void draw_unlock_indicator() { /* Initialise the surface if not yet done */ if (unlock_indicator_surface == NULL) { button_diameter_physical = ceil(scaling_factor() * BUTTON_DIAMETER); DEBUG("scaling_factor is %.f, physical diameter is %d px\n", scaling_factor(), button_diameter_physical); unlock_indicator_surface = cairo_image_surface_create( CAIRO_FORMAT_ARGB32, button_diameter_physical, button_diameter_physical); } cairo_t *ctx = cairo_create(unlock_indicator_surface); /* clear the surface */ cairo_save(ctx); cairo_set_operator(ctx, CAIRO_OPERATOR_CLEAR); cairo_paint(ctx); cairo_restore(ctx); if (unlock_state >= STATE_KEY_PRESSED && unlock_indicator) { cairo_scale(ctx, scaling_factor(), scaling_factor()); /* Draw a (centered) circle with transparent background. */ cairo_set_line_width(ctx, 10.0); cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, 0 /* start */, 2 * M_PI /* end */); /* Use the appropriate color for the different PAM states * (currently verifying, wrong password, or default) */ switch (pam_state) { case STATE_PAM_VERIFY: cairo_set_source_rgba(ctx, 0, 114.0 / 255, 255.0 / 255, 0.75); break; case STATE_PAM_WRONG: cairo_set_source_rgba(ctx, 250.0 / 255, 0, 0, 0.75); break; default: cairo_set_source_rgba(ctx, 0, 0, 0, 0.75); break; } cairo_fill_preserve(ctx); switch (pam_state) { case STATE_PAM_VERIFY: cairo_set_source_rgb(ctx, 51.0 / 255, 0, 250.0 / 255); break; case STATE_PAM_WRONG: cairo_set_source_rgb(ctx, 125.0 / 255, 51.0 / 255, 0); break; case STATE_PAM_IDLE: cairo_set_source_rgb(ctx, 51.0 / 255, 125.0 / 255, 0); break; } cairo_stroke(ctx); /* Draw an inner seperator line. */ cairo_set_source_rgb(ctx, 0, 0, 0); cairo_set_line_width(ctx, 2.0); cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS - 5 /* radius */, 0, 2 * M_PI); cairo_stroke(ctx); cairo_set_line_width(ctx, 10.0); /* Display a (centered) text of the current PAM state. */ char *text = NULL; /* We don't want to show more than a 3-digit number. */ char buf[4]; cairo_set_source_rgb(ctx, 0, 0, 0); cairo_set_font_size(ctx, 28.0); switch (pam_state) { case STATE_PAM_VERIFY: text = "verifying…"; break; case STATE_PAM_WRONG: text = "wrong!"; break; default: if (show_failed_attempts && failed_attempts > 0) { if (failed_attempts > 999) { text = "> 999"; } else { snprintf(buf, sizeof(buf), "%d", failed_attempts); text = buf; } cairo_set_source_rgb(ctx, 1, 0, 0); cairo_set_font_size(ctx, 32.0); } break; } if (text) { cairo_text_extents_t extents; double x, y; cairo_text_extents(ctx, text, &extents); x = BUTTON_CENTER - ((extents.width / 2) + extents.x_bearing); y = BUTTON_CENTER - ((extents.height / 2) + extents.y_bearing); cairo_move_to(ctx, x, y); cairo_show_text(ctx, text); cairo_close_path(ctx); } if (pam_state == STATE_PAM_WRONG && (modifier_string != NULL)) { cairo_text_extents_t extents; double x, y; cairo_set_font_size(ctx, 14.0); cairo_text_extents(ctx, modifier_string, &extents); x = BUTTON_CENTER - ((extents.width / 2) + extents.x_bearing); y = BUTTON_CENTER - ((extents.height / 2) + extents.y_bearing) + 28.0; cairo_move_to(ctx, x, y); cairo_show_text(ctx, modifier_string); cairo_close_path(ctx); } /* After the user pressed any valid key or the backspace key, we * highlight a random part of the unlock indicator to confirm this * keypress. */ if (unlock_state == STATE_KEY_ACTIVE || unlock_state == STATE_BACKSPACE_ACTIVE) { cairo_new_sub_path(ctx); double highlight_start = (rand() % (int)(2 * M_PI * 100)) / 100.0; cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, highlight_start, highlight_start + (M_PI / 3.0)); if (unlock_state == STATE_KEY_ACTIVE) { /* For normal keys, we use a lighter green. */ cairo_set_source_rgb(ctx, 51.0 / 255, 219.0 / 255, 0); } else { /* For backspace, we use red. */ cairo_set_source_rgb(ctx, 219.0 / 255, 51.0 / 255, 0); } cairo_stroke(ctx); /* Draw two little separators for the highlighted part of the * unlock indicator. */ cairo_set_source_rgb(ctx, 0, 0, 0); cairo_arc(ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, highlight_start /* start */, highlight_start + (M_PI / 128.0) /* end */); cairo_stroke(ctx); cairo_arc( ctx, BUTTON_CENTER /* x */, BUTTON_CENTER /* y */, BUTTON_RADIUS /* radius */, highlight_start + (M_PI / 3.0) /* start */, (highlight_start + (M_PI / 3.0)) + (M_PI / 128.0) /* end */); cairo_stroke(ctx); } } cairo_destroy(ctx); }
/* * Draws global image with fill color onto a pixmap with the given * resolution and returns it. * */ xcb_pixmap_t draw_image(uint32_t *resolution) { xcb_pixmap_t bg_pixmap = XCB_NONE; int button_diameter_physical = ceil(scaling_factor() * BUTTON_DIAMETER); DEBUG("scaling_factor is %.f, physical diameter is %d px\n", scaling_factor(), button_diameter_physical); if (!vistype) vistype = get_root_visual_type(screen); bg_pixmap = create_bg_pixmap(conn, screen, resolution, color); /* Initialize cairo: Create one in-memory surface to render the unlock * indicator on, create one XCB surface to actually draw (one or more, * depending on the amount of screens) unlock indicators on. */ cairo_surface_t *output = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, resolution[0], resolution[1]); cairo_t *ctx = cairo_create(output); cairo_surface_t *xcb_output = cairo_xcb_surface_create(conn, bg_pixmap, vistype, resolution[0], resolution[1]); cairo_t *xcb_ctx = cairo_create(xcb_output); if (img) { if (!tile) { cairo_set_source_surface(xcb_ctx, img, 0, 0); cairo_paint(xcb_ctx); } else { /* create a pattern and fill a rectangle as big as the screen */ cairo_pattern_t *pattern; pattern = cairo_pattern_create_for_surface(img); cairo_set_source(xcb_ctx, pattern); cairo_pattern_set_extend(pattern, CAIRO_EXTEND_REPEAT); cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]); cairo_fill(xcb_ctx); cairo_pattern_destroy(pattern); } } else { char strgroups[3][3] = {{color[0], color[1], '\0'}, {color[2], color[3], '\0'}, {color[4], color[5], '\0'}}; uint32_t rgb16[3] = {(strtol(strgroups[0], NULL, 16)), (strtol(strgroups[1], NULL, 16)), (strtol(strgroups[2], NULL, 16))}; cairo_set_source_rgb(xcb_ctx, rgb16[0] / 255.0, rgb16[1] / 255.0, rgb16[2] / 255.0); cairo_rectangle(xcb_ctx, 0, 0, resolution[0], resolution[1]); cairo_fill(xcb_ctx); } if (unlock_indicator) { cairo_scale(ctx, scaling_factor(), scaling_factor()); cairo_set_source_rgb(ctx, 1, 1, 1); cairo_set_font_size(ctx, 60.0); cairo_select_font_face(ctx, "sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); if (pam_state == STATE_PAM_VERIFY) { passwdlength = 0; } if (unlock_state == STATE_KEY_ACTIVE) { passwdlength = passwdlength + 1; } else if (unlock_state == STATE_BACKSPACE_ACTIVE && passwdlength > 0){ passwdlength = passwdlength - 1; } else if (unlock_state == STATE_ESCAPE_ACTIVE) { passwdlength = 0; } char passwd[passwdlength + 1]; for (int i = 0; i < passwdlength; ++i) { passwd[i] = '*'; } passwd[passwdlength] = '\0'; cairo_text_extents_t extents; double x, y; cairo_text_extents(ctx, passwd, &extents); x = BUTTON_RADIUS - ((extents.width / 2) + extents.x_bearing); y = BUTTON_RADIUS - ((extents.height / 2) + extents.y_bearing); cairo_move_to(ctx, x, y); /* cairo_show_text(ctx, passwd); */ cairo_text_path(ctx, passwd); cairo_fill_preserve(ctx); cairo_set_source_rgb(ctx, 0, 0, 0); cairo_set_line_width(ctx, 1.0); cairo_stroke(ctx); cairo_close_path(ctx); } if (xr_screens > 0) { /* Composite the unlock indicator in the middle of each screen. */ for (int screen = 0; screen < xr_screens; screen++) { int x = (xr_resolutions[screen].x + ((xr_resolutions[screen].width / 2) - (button_diameter_physical / 2))); int y = (xr_resolutions[screen].y + ((xr_resolutions[screen].height / 2) - (button_diameter_physical / 2))); cairo_set_source_surface(xcb_ctx, output, x, y); cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical); cairo_fill(xcb_ctx); } } else { /* We have no information about the screen sizes/positions, so we just * place the unlock indicator in the middle of the X root window and * hope for the best. */ int x = (last_resolution[0] / 2) - (button_diameter_physical / 2); int y = (last_resolution[1] / 2) - (button_diameter_physical / 2); cairo_set_source_surface(xcb_ctx, output, x, y); cairo_rectangle(xcb_ctx, x, y, button_diameter_physical, button_diameter_physical); cairo_fill(xcb_ctx); } cairo_surface_destroy(xcb_output); cairo_surface_destroy(output); cairo_destroy(ctx); cairo_destroy(xcb_ctx); return bg_pixmap; }