static gboolean process (GeglOperation *operation, GeglBuffer *input, GeglBuffer *output, const GeglRectangle *result, gint level) { GeglProperties *o = GEGL_PROPERTIES (operation); gint width = MAX(MAX (o->width, o->x0), o->x1); gint height = MAX(MAX (o->height, o->y0), o->y1); { GeglRectangle extent = {0,0,width,height}; output = gegl_buffer_new (&extent, babl_format ("B'aG'aR'aA u8")); } { guchar *buf = g_new0 (guchar, width * height * 4); cairo_t *cr; cairo_surface_t *surface = cairo_image_surface_create_for_data (buf, CAIRO_FORMAT_ARGB32, width, height, width * 4); cr = cairo_create (surface); /* cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); cairo_rectangle (cr, 0,0, o->width, o->height); cairo_fill (cr);*/ #define val2y(val) (o->height - (val - o->min) * o->height / (o->max-o->min)) cairo_set_source_rgba (cr, .0, .0, .8, 0.5); cairo_move_to (cr, 0, val2y(0.0)); cairo_line_to (cr, o->width, val2y(0.0)); cairo_set_source_rgba (cr, .8, .8, .0, 0.5); cairo_move_to (cr, 0, val2y(1.0)); cairo_line_to (cr, o->width, val2y(1.0)); cairo_stroke (cr); cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); { gint x; cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 1.0); for (x=0;x<o->width;x++) { gfloat t = (1.0*x)/o->width; gint sx = ((1.0-t) * o->x0) + (t * o->x1); gint sy = ((1.0-t) * o->y0) + (t * o->y1); cairo_line_to (cr, x, val2y(buffer_sample(input,sx,sy,0))); } cairo_stroke (cr); } { gint x; cairo_set_source_rgba (cr, 0.0, 1.0, 0.0, 1.0); for (x=0;x<o->width;x++) { gfloat t = (1.0*x)/o->width; gint sx = ((1.0-t) * o->x0) + (t * o->x1); gint sy = ((1.0-t) * o->y0) + (t * o->y1); cairo_line_to (cr, x, val2y(buffer_sample(input,sx,sy,1))); } cairo_stroke (cr); } { gint x; cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 1.0); for (x=0;x<o->width;x++) { gfloat t = (1.0*x)/o->width; gint sx = ((1.0-t) * o->x0) + (t * o->x1); gint sy = ((1.0-t) * o->y0) + (t * o->y1); cairo_line_to (cr, x, val2y(buffer_sample(input,sx,sy,2))); } cairo_stroke (cr); } cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.4); cairo_move_to (cr, o->x0, o->y0); cairo_line_to (cr, o->x1, o->y1); cairo_stroke (cr); gegl_buffer_set (output, NULL, 0, babl_format ("B'aG'aR'aA u8"), buf, GEGL_AUTO_ROWSTRIDE); } return TRUE; }
static gboolean _lib_navigation_draw_callback(GtkWidget *widget, cairo_t *crf, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_navigation_t *d = (dt_lib_navigation_t *)self->data; const int inset = DT_NAVIGATION_INSET; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width, height = allocation.height; dt_develop_t *dev = darktable.develop; /* double buffering of image data: only take new data if valid */ if(dev->preview_pipe->backbuf && dev->preview_status == DT_DEV_PIXELPIPE_VALID) { /* re-allocate in case of changed image dimensions */ if(d->buffer == NULL || dev->preview_pipe->backbuf_width != d->wd || dev->preview_pipe->backbuf_height != d->ht) { g_free(d->buffer); d->wd = dev->preview_pipe->backbuf_width; d->ht = dev->preview_pipe->backbuf_height; d->buffer = g_malloc0((size_t)d->wd * d->ht * 4 * sizeof(unsigned char)); } /* update buffer if new data is available */ if(d->buffer && dev->preview_pipe->input_timestamp > d->timestamp) { dt_pthread_mutex_t *mutex = &dev->preview_pipe->backbuf_mutex; dt_pthread_mutex_lock(mutex); memcpy(d->buffer, dev->preview_pipe->backbuf, (size_t)d->wd * d->ht * 4 * sizeof(unsigned char)); d->timestamp = dev->preview_pipe->input_timestamp; dt_pthread_mutex_unlock(mutex); } } /* get the current style */ cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); GtkStyleContext *context = gtk_widget_get_style_context(widget); gtk_render_background(context, cr, 0, 0, allocation.width, allocation.height); width -= 2 * inset; height -= 2 * inset; cairo_translate(cr, inset, inset); /* draw navigation image if available */ if(d->buffer) { cairo_save(cr); const int wd = d->wd; const int ht = d->ht; const float scale = fminf(width / (float)wd, height / (float)ht); const int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, wd); cairo_surface_t *surface = cairo_image_surface_create_for_data(d->buffer, CAIRO_FORMAT_RGB24, wd, ht, stride); cairo_translate(cr, width / 2.0, height / 2.0f); cairo_scale(cr, scale, scale); cairo_translate(cr, -.5f * wd, -.5f * ht); // draw shadow around float alpha = 1.0f; for(int k = 0; k < 4; k++) { cairo_rectangle(cr, -k / scale, -k / scale, wd + 2 * k / scale, ht + 2 * k / scale); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.6f; cairo_fill(cr); } cairo_rectangle(cr, 0, 0, wd - 2, ht - 1); cairo_set_source_surface(cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST); cairo_fill(cr); cairo_surface_destroy(surface); // draw box where we are dt_dev_zoom_t zoom = dt_control_get_dev_zoom(); int closeup = dt_control_get_dev_closeup(); float zoom_x = dt_control_get_dev_zoom_x(); float zoom_y = dt_control_get_dev_zoom_y(); const float min_scale = dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, closeup ? 2.0 : 1.0, 0); const float cur_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2.0 : 1.0, 0); // avoid numerical instability for small resolutions: double h, w; if(cur_scale > min_scale) { float boxw = 1, boxh = 1; dt_dev_check_zoom_bounds(darktable.develop, &zoom_x, &zoom_y, zoom, closeup, &boxw, &boxh); cairo_translate(cr, wd * (.5f + zoom_x), ht * (.5f + zoom_y)); cairo_set_source_rgb(cr, 0., 0., 0.); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.f / scale)); boxw *= wd; boxh *= ht; cairo_rectangle(cr, -boxw / 2 - 1, -boxh / 2 - 1, boxw + 2, boxh + 2); cairo_stroke(cr); cairo_set_source_rgb(cr, 1., 1., 1.); cairo_rectangle(cr, -boxw / 2, -boxh / 2, boxw, boxh); cairo_stroke(cr); } cairo_restore(cr); if(fabsf(cur_scale - min_scale) > 0.001f) { /* Zoom % */ PangoLayout *layout; PangoRectangle ink; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); const float fontsize = DT_PIXEL_APPLY_DPI(11); pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE); pango_layout_set_font_description(layout, desc); cairo_translate(cr, 0, height); cairo_set_source_rgba(cr, 1., 1., 1., 0.5); cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); char zoomline[5]; snprintf(zoomline, sizeof(zoomline), "%.0f%%", cur_scale * 100); pango_layout_set_text(layout, zoomline, -1); pango_layout_get_pixel_extents(layout, &ink, NULL); h = d->zoom_h = ink.height; w = d->zoom_w = ink.width; cairo_move_to(cr, width - w - h * 1.1 - ink.x, - fontsize); cairo_save(cr); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0)); GdkRGBA *color; gtk_style_context_get(context, gtk_widget_get_state_flags(widget), "background-color", &color, NULL); gdk_cairo_set_source_rgba(cr, color); pango_cairo_layout_path(cr, layout); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_fill(cr); cairo_restore(cr); gdk_rgba_free(color); pango_font_description_free(desc); g_object_unref(layout); } else { // draw the zoom-to-fit icon cairo_translate(cr, 0, height); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); static int height = -1; if(height == -1) { PangoLayout *layout; PangoRectangle ink; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); pango_font_description_set_absolute_size(desc, DT_PIXEL_APPLY_DPI(11) * PANGO_SCALE); pango_layout_set_font_description(layout, desc); pango_layout_set_text(layout, "100%", -1); // dummy text, just to get the height pango_layout_get_pixel_extents(layout, &ink, NULL); height = ink.height; pango_font_description_free(desc); g_object_unref(layout); } h = d->zoom_h = height; w = h * 1.5; float sp = h * 0.6; d->zoom_w = w + sp; cairo_move_to(cr, width - w - h - sp, -1.0 * h); cairo_rectangle(cr, width - w - h - sp, -1.0 * h, w, h); cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); cairo_fill(cr); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0)); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_move_to(cr, width - w * 0.8 - h - sp, -1.0 * h); cairo_line_to(cr, width - w - h - sp, -1.0 * h); cairo_line_to(cr, width - w - h - sp, -0.7 * h); cairo_stroke(cr); cairo_move_to(cr, width - w - h - sp, -0.3 * h); cairo_line_to(cr, width - w - h - sp, 0); cairo_line_to(cr, width - w * 0.8 - h - sp, 0); cairo_stroke(cr); cairo_move_to(cr, width - w * 0.2 - h - sp, 0); cairo_line_to(cr, width - h - sp, 0); cairo_line_to(cr, width - h - sp, -0.3 * h); cairo_stroke(cr); cairo_move_to(cr, width - h - sp, -0.7 * h); cairo_line_to(cr, width - h - sp, -1.0 * h); cairo_line_to(cr, width - w * 0.2 - h - sp, -1.0 * h); cairo_stroke(cr); } cairo_move_to(cr, width - 0.95 * h, -0.9 * h); cairo_line_to(cr, width - 0.05 * h, -0.9 * h); cairo_line_to(cr, width - 0.5 * h, -0.1 * h); cairo_fill(cr); } /* blit memsurface into widget */ cairo_destroy(cr); cairo_set_source_surface(crf, cst, 0, 0); cairo_paint(crf); cairo_surface_destroy(cst); return TRUE; }
static void gtk_css_image_builtin_draw_option (GtkCssImage *image, cairo_t *cr, double width, double height, gboolean checked, gboolean inconsistent) { GtkCssImageBuiltin *builtin = GTK_CSS_IMAGE_BUILTIN (image); gint x, y, exterior_size, interior_size, thickness, pad; exterior_size = MIN (width, height); if (exterior_size % 2 == 0) /* Ensure odd */ exterior_size -= 1; x = - (1 + exterior_size - width) / 2; y = - (1 + exterior_size - height) / 2; if (builtin->border_width > 0) { cairo_set_line_width (cr, builtin->border_width); cairo_new_sub_path (cr); cairo_arc (cr, x + exterior_size / 2., y + exterior_size / 2., (exterior_size - 1) / 2., 0, 2 * G_PI); gdk_cairo_set_source_rgba (cr, &builtin->bg_color); cairo_fill_preserve (cr); gdk_cairo_set_source_rgba (cr, &builtin->border_color); cairo_stroke (cr); } gdk_cairo_set_source_rgba (cr, &builtin->fg_color); /* FIXME: thickness */ thickness = 1; if (inconsistent) { gint line_thickness; pad = thickness + MAX (1, (exterior_size - 2 * thickness) / 9); interior_size = MAX (1, exterior_size - 2 * pad); if (interior_size < 7) { interior_size = 7; pad = MAX (0, (exterior_size - interior_size) / 2); } line_thickness = MAX (1, (3 + interior_size * 2) / 7); cairo_rectangle (cr, x + pad, y + pad + (interior_size - line_thickness) / 2., interior_size, line_thickness); cairo_fill (cr); } if (checked) { pad = thickness + MAX (1, 2 * (exterior_size - 2 * thickness) / 9); interior_size = MAX (1, exterior_size - 2 * pad); if (interior_size < 5) { interior_size = 7; pad = MAX (0, (exterior_size - interior_size) / 2); } cairo_new_sub_path (cr); cairo_arc (cr, x + pad + interior_size / 2., y + pad + interior_size / 2., interior_size / 2., 0, 2 * G_PI); cairo_fill (cr); } }
/* Set gadget's background */ gboolean on_expose_event (GtkWidget *widget, GdkEventExpose *event, temp_notifier_gadget_s *core) { cairo_t *cr; double x0 = 5.0; double y0 = 15.0; double rect_width = core->width - 10; double rect_height = core->height - 25; double radius = 40; double x1,y1; cr = gdk_cairo_create (widget->window); /* Set gadget background transparent */ cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 0.0); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_paint (cr); x1 = x0 + rect_width; y1 = y0 + rect_height; if (!rect_width || !rect_height) return; cairo_move_to (cr, x0, (y0 + y1)/2); cairo_curve_to (cr, x0 ,y0, x0, y0, (x0 + x1)/2, y0); cairo_curve_to (cr, x1, y0, x1, y0, x1, (y0 + y1)/2); cairo_curve_to (cr, x1, y1, x1, y1, (x1 + x0)/2, y1); cairo_curve_to (cr, x0, y1, x0, y1, x0, (y0 + y1)/2); cairo_close_path (cr); cairo_set_source_rgba (cr, (float) core->gadget.red / 65535.0, (float) core->gadget.green / 65535.0, (float) core->gadget.blue / 65535.0, 1); cairo_fill_preserve (cr); switch (core->border_value) { case 1: gdk_color_parse ("#CC4400", &core->border); break; case 2: gdk_color_parse ("#CC6600", &core->border); break; case 3: gdk_color_parse ("#CCBB00", &core->border); break; case 4: gdk_color_parse ("#CCDD00", &core->border); break; case 5: gdk_color_parse ("#99DD00", &core->border); break; case 6: gdk_color_parse ("#00EE44", &core->border); break; case 7: /* Super green */ gdk_color_parse ("#00BB44", &core->border); break; case -1: /* Super red */ gdk_color_parse ("#002200", &core->border); break; default: gdk_color_parse ("#CCCCCC", &core->border); break; } cairo_set_source_rgba (cr, (float) core->border.red / 65535.0, (float) core->border.green / 65535.0, (float) core->border.blue / 65535.0, core->border_transparency); cairo_set_line_width (cr, 3.0); cairo_stroke (cr); cairo_destroy(cr); return FALSE; }
static gboolean _lib_navigation_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_navigation_t *d = (dt_lib_navigation_t *)self->data; const int inset = DT_NAVIGATION_INSET; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width, height = allocation.height; dt_develop_t *dev = darktable.develop; if (dev->preview_dirty) return FALSE; /* get the current style */ GtkStyle *style=gtk_rc_get_style_by_paths(gtk_settings_get_default(), NULL,"GtkWidget", GTK_TYPE_WIDGET); if(!style) style = gtk_rc_get_style(widget); cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); /* fill background */ cairo_set_source_rgb(cr, style->bg[0].red/65535.0, style->bg[0].green/65535.0, style->bg[0].blue/65535.0); cairo_paint(cr); width -= 2*inset; height -= 2*inset; cairo_translate(cr, inset, inset); /* draw navigation image if available */ if(dev->preview_pipe->backbuf && !dev->preview_dirty) { dt_pthread_mutex_t *mutex = &dev->preview_pipe->backbuf_mutex; dt_pthread_mutex_lock(mutex); const int wd = dev->preview_pipe->backbuf_width; const int ht = dev->preview_pipe->backbuf_height; const float scale = fminf(width/(float)wd, height/(float)ht); const int stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, wd); cairo_surface_t *surface = cairo_image_surface_create_for_data (dev->preview_pipe->backbuf, CAIRO_FORMAT_RGB24, wd, ht, stride); cairo_translate(cr, width/2.0, height/2.0f); cairo_scale(cr, scale, scale); cairo_translate(cr, -.5f*wd, -.5f*ht); // draw shadow around float alpha = 1.0f; for(int k=0; k<4; k++) { cairo_rectangle(cr, -k/scale, -k/scale, wd + 2*k/scale, ht + 2*k/scale); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.6f; cairo_fill(cr); } cairo_rectangle(cr, 0, 0, wd-2, ht-1); cairo_set_source_surface (cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST); cairo_fill(cr); cairo_surface_destroy (surface); dt_pthread_mutex_unlock(mutex); // draw box where we are dt_dev_zoom_t zoom; int closeup; float zoom_x, zoom_y; DT_CTL_GET_GLOBAL(zoom, dev_zoom); DT_CTL_GET_GLOBAL(closeup, dev_closeup); DT_CTL_GET_GLOBAL(zoom_x, dev_zoom_x); DT_CTL_GET_GLOBAL(zoom_y, dev_zoom_y); const float min_scale = dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, closeup ? 2.0 : 1.0, 0); const float cur_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2.0 : 1.0, 0); // avoid numerical instability for small resolutions: double h,w; if(cur_scale > min_scale) { float boxw = 1, boxh = 1; dt_dev_check_zoom_bounds(darktable.develop, &zoom_x, &zoom_y, zoom, closeup, &boxw, &boxh); cairo_translate(cr, wd*(.5f+zoom_x), ht*(.5f+zoom_y)); cairo_set_source_rgb(cr, 0., 0., 0.); cairo_set_line_width(cr, 1.f/scale); boxw *= wd; boxh *= ht; cairo_rectangle(cr, -boxw/2-1, -boxh/2-1, boxw+2, boxh+2); cairo_stroke(cr); cairo_set_source_rgb(cr, 1., 1., 1.); cairo_rectangle(cr, -boxw/2, -boxh/2, boxw, boxh); cairo_stroke(cr); } if(fabsf(cur_scale - min_scale) > 0.001f) { /* Zoom % */ cairo_identity_matrix(cr); cairo_translate(cr, 0, height); cairo_set_source_rgba(cr, 1., 1., 1., 0.5); cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size (cr, 11); char zoomline[5]; snprintf(zoomline, 5, "%.0f%%", cur_scale*100); cairo_text_extents_t ext; cairo_text_extents(cr,zoomline,&ext); h = d->zoom_h = ext.height; w = d->zoom_w = ext.width; cairo_move_to(cr,width-w-h*1.1,0); cairo_save(cr); cairo_set_line_width(cr, 2.0); cairo_set_source_rgb(cr, style->bg[0].red/65535.0, style->bg[0].green/65535.0, style->bg[0].blue/65535.0); cairo_text_path(cr, zoomline); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_fill(cr); cairo_restore(cr); } else { //draw the zoom-to-fit icon cairo_identity_matrix(cr); cairo_translate(cr, 0, height); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_text_extents_t ext; cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size (cr, 11); cairo_text_extents(cr,"100%",&ext); //dummy text, just to get the height h = d->zoom_h = ext.height; w = h*1.5; float sp = h*0.6; d->zoom_w = w + sp; cairo_move_to(cr,width-w-h-sp,-1.0*h); cairo_rectangle(cr,width-w-h-sp,-1.0*h,w,h); cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); cairo_fill(cr); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_move_to(cr,width-w*0.8-h-sp,-1.0*h); cairo_line_to(cr,width-w-h-sp,-1.0*h); cairo_line_to(cr,width-w-h-sp,-0.7*h); cairo_stroke(cr); cairo_move_to(cr,width-w-h-sp,-0.3*h); cairo_line_to(cr,width-w-h-sp,0); cairo_line_to(cr,width-w*0.8-h-sp,0); cairo_stroke(cr); cairo_move_to(cr,width-w*0.2-h-sp,0); cairo_line_to(cr,width-h-sp,0); cairo_line_to(cr,width-h-sp,-0.3*h); cairo_stroke(cr); cairo_move_to(cr,width-h-sp,-0.7*h); cairo_line_to(cr,width-h-sp,-1.0*h); cairo_line_to(cr,width-w*0.2-h-sp,-1.0*h); cairo_stroke(cr); } cairo_move_to(cr, width-0.95*h, -0.9*h); cairo_line_to(cr, width-0.05*h, -0.9*h); cairo_line_to(cr, width-0.5*h, -0.1*h); cairo_fill(cr); } /* blit memsurface into widget */ 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 void _awn_overlay_progress_circle_render (AwnOverlay* _overlay, GtkWidget *widget, cairo_t * cr, gint width, gint height) { AwnOverlayProgressCircle * overlay = AWN_OVERLAY_PROGRESS_CIRCLE(_overlay); AwnOverlayProgressCirclePrivate *priv; DesktopAgnosticColor * fg_color; DesktopAgnosticColor * bg_color; DesktopAgnosticColor * outline_color; gdouble percent_complete, x_pos, y_pos; AwnOverlayCoord coord; priv = AWN_OVERLAY_PROGRESS_CIRCLE_GET_PRIVATE (overlay); g_object_get (overlay, "percent-complete",&percent_complete, NULL); if (priv->fg_color) { fg_color = priv->fg_color; g_object_ref (fg_color); } else { fg_color = desktop_agnostic_color_new(&widget->style->bg[GTK_STATE_ACTIVE], 0.7*G_MAXUSHORT); } if (priv->bg_color) { bg_color = priv->bg_color; g_object_ref (bg_color); } else { bg_color = desktop_agnostic_color_new(&widget->style->fg[GTK_STATE_ACTIVE], 0.2 * G_MAXUSHORT); } if (priv->outline_color) { outline_color = priv->outline_color; g_object_ref (outline_color); } else { outline_color = desktop_agnostic_color_new(&widget->style->fg[GTK_STATE_ACTIVE], G_MAXUSHORT); } awn_overlay_move_to (_overlay, cr, width, height, width * priv->scale, height * priv->scale, &coord); x_pos = coord.x / width + priv->scale / 2.0; y_pos = coord.y / height + priv->scale / 2.0; cairo_save (cr); cairo_scale (cr, width, height); cairo_set_line_width (cr, 2. / (width + height)); awn_cairo_set_source_color (cr,bg_color); cairo_arc (cr, x_pos, y_pos, priv->scale/2.0, 0, 2 * M_PI); cairo_fill (cr); cairo_arc (cr, x_pos, y_pos, priv->scale/2.0, -0.5 * M_PI, 2 * (percent_complete/100.0) * M_PI -0.5 * M_PI ); cairo_line_to (cr, x_pos, y_pos); cairo_close_path (cr); awn_cairo_set_source_color (cr,fg_color); cairo_fill (cr); if (percent_complete > 0) { cairo_arc (cr, x_pos, y_pos, priv->scale/2.0, -0.5 * M_PI, 2 * (percent_complete/100.0) * M_PI -0.5 * M_PI ); if (percent_complete < 100) { cairo_line_to (cr, x_pos, y_pos); cairo_close_path (cr); } awn_cairo_set_source_color (cr, outline_color); cairo_stroke (cr); } cairo_restore (cr); g_object_unref (fg_color); g_object_unref (bg_color); g_object_unref (outline_color); }
static void makeplot(const char* plotfn, char* bgimgfn, int W, int H, int Nfield, double* fieldpix, double* fieldsigma2s, int Nindex, double* indexpix, int besti, int* theta, double* crpix, int* testperm, double * qc) { int i; plot_args_t pargs; plotimage_t* img; cairo_t* cairo; int ti; logmsg("Creating plot %s\n", plotfn); plotstuff_init(&pargs); pargs.outformat = PLOTSTUFF_FORMAT_PNG; pargs.outfn = plotfn; pargs.fontsize = 12; if (bgimgfn) { img = plotstuff_get_config(&pargs, "image"); img->format = PLOTSTUFF_FORMAT_JPG; plot_image_set_filename(img, bgimgfn); plot_image_setsize(&pargs, img); plotstuff_run_command(&pargs, "image"); } else { float rgba[4] = {0, 0, 0.1, 1.0}; plotstuff_set_size(&pargs, W, H); //plotstuff_init2(&pargs); plotstuff_set_rgba(&pargs, rgba); plotstuff_run_command(&pargs, "fill"); } cairo = pargs.cairo; // red circles around every field star. cairo_set_color(cairo, "gray"); for (i=0; i<Nfield; i++) { cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CIRCLE, fieldpix[2*i+0], fieldpix[2*i+1], 2.0 * sqrt(fieldsigma2s[i])); cairo_stroke(cairo); } // green crosshairs at every index star. cairo_set_color(cairo, "green"); for (i=0; i<Nindex; i++) { cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_XCROSSHAIR, indexpix[2*i+0], indexpix[2*i+1], 3); cairo_stroke(cairo); } // thick white circles for corresponding field stars. cairo_set_line_width(cairo, 2); for (ti=0; ti<=besti; ti++) { if (testperm) i = testperm[ti]; else i = ti; //printf("field %i -> index %i\n", i, theta[i]); if (theta[i] < 0) continue; cairo_set_color(cairo, "white"); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CIRCLE, fieldpix[2*i+0], fieldpix[2*i+1], 2.0 * sqrt(fieldsigma2s[i])); cairo_stroke(cairo); // thick cyan crosshairs for corresponding index stars. cairo_set_color(cairo, "cyan"); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_XCROSSHAIR, indexpix[2*theta[i]+0], indexpix[2*theta[i]+1], 3); cairo_stroke(cairo); } cairo_set_line_width(cairo, 2); //for (i=0; i<=besti; i++) { for (ti=0; ti<Nfield; ti++) { anbool mark = TRUE; if (testperm) i = testperm[ti]; else i = ti; switch (theta[i]) { case THETA_DISTRACTOR: cairo_set_color(cairo, "red"); break; case THETA_CONFLICT: cairo_set_color(cairo, "yellow"); break; case THETA_FILTERED: cairo_set_color(cairo, "orange"); break; default: if (theta[i] < 0) { cairo_set_color(cairo, "gray"); } else { cairo_set_color(cairo, "white"); } mark = FALSE; } if (mark) { cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CIRCLE, fieldpix[2*i+0], fieldpix[2*i+1], 2.0 * sqrt(fieldsigma2s[i])); cairo_stroke(cairo); } if (ti <= MAX(besti, 10)) { char label[32]; sprintf(label, "%i", i); plotstuff_text_xy(&pargs, fieldpix[2*i+0], fieldpix[2*i+1], label); } if (i == besti) { cairo_set_line_width(cairo, 1); } } if (crpix) { cairo_set_color(cairo, "yellow"); cairo_set_line_width(cairo, 4); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CROSSHAIR, crpix[0], crpix[1], 10); cairo_stroke(cairo); } if (qc) { cairo_set_color(cairo, "skyblue"); cairo_set_line_width(cairo, 4); cairoutils_draw_marker(cairo, CAIROUTIL_MARKER_CROSSHAIR, qc[0], qc[1], 10); cairo_stroke(cairo); } plotstuff_output(&pargs); logmsg("Wrote plot %s\n", plotfn); }
static gboolean checker_draw(GtkWidget *widget, cairo_t *crf, gpointer user_data) { dt_iop_module_t *self = (dt_iop_module_t *)user_data; dt_iop_colorchecker_gui_data_t *g = (dt_iop_colorchecker_gui_data_t *)self->gui_data; dt_iop_colorchecker_params_t *p = (dt_iop_colorchecker_params_t *)self->params; 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 bg cairo_set_source_rgb(cr, .2, .2, .2); cairo_paint(cr); const float *picked_mean = self->picked_color; int besti = 0, bestj = 0; cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); int cells_x = 6, cells_y = 4; if(p->num_patches > 24) { cells_x = 7; cells_y = 7; } for(int j = 0; j < cells_y; j++) { for(int i = 0; i < cells_x; i++) { double rgb[3] = { 0.5, 0.5, 0.5 }; // Lab: rgb grey converted to Lab cmsCIELab Lab; const int patch = i + j*cells_x; if(patch >= p->num_patches) continue; Lab.L = p->source_L[patch]; Lab.a = p->source_a[patch]; Lab.b = p->source_b[patch]; if((picked_mean[0] - Lab.L)*(picked_mean[0] - Lab.L) + (picked_mean[1] - Lab.a)*(picked_mean[1] - Lab.a) + (picked_mean[2] - Lab.b)*(picked_mean[2] - Lab.b) < (picked_mean[0] - p->source_L[cells_x*bestj+besti])* (picked_mean[0] - p->source_L[cells_x*bestj+besti])+ (picked_mean[1] - p->source_a[cells_x*bestj+besti])* (picked_mean[1] - p->source_a[cells_x*bestj+besti])+ (picked_mean[2] - p->source_b[cells_x*bestj+besti])* (picked_mean[2] - p->source_b[cells_x*bestj+besti])) { besti = i; bestj = j; } cmsDoTransform(g->xform, &Lab, rgb, 1); cairo_set_source_rgb(cr, rgb[0], rgb[1], rgb[2]); cairo_rectangle(cr, width * i / (float)cells_x, height * j / (float)cells_y, width / (float)cells_x - DT_PIXEL_APPLY_DPI(1), height / (float)cells_y - DT_PIXEL_APPLY_DPI(1)); cairo_fill(cr); if(fabsf(p->target_L[patch] - p->source_L[patch]) > 1e-5f || fabsf(p->target_a[patch] - p->source_a[patch]) > 1e-5f || fabsf(p->target_b[patch] - p->source_b[patch]) > 1e-5f) { cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.)); cairo_set_source_rgb(cr, 0.8, 0.8, 0.8); cairo_rectangle(cr, width * i / (float)cells_x + DT_PIXEL_APPLY_DPI(1), height * j / (float)cells_y + DT_PIXEL_APPLY_DPI(1), width / (float)cells_x - DT_PIXEL_APPLY_DPI(3), height / (float)cells_y - DT_PIXEL_APPLY_DPI(3)); cairo_stroke(cr); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.)); cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); cairo_rectangle(cr, width * i / (float)cells_x + DT_PIXEL_APPLY_DPI(2), height * j / (float)cells_y + DT_PIXEL_APPLY_DPI(2), width / (float)cells_x - DT_PIXEL_APPLY_DPI(5), height / (float)cells_y - DT_PIXEL_APPLY_DPI(5)); cairo_stroke(cr); } } } // highlight patch that is closest to picked colour, // or the one selected in the combobox. if(self->request_color_pick == DT_REQUEST_COLORPICK_OFF) { int i = dt_bauhaus_combobox_get(g->combobox_patch); besti = i % cells_x; bestj = i / cells_x; g->drawn_patch = cells_x * bestj + besti; } else { // freshly picked, also select it in gui: int pick = self->request_color_pick; g->drawn_patch = cells_x * bestj + besti; darktable.gui->reset = 1; dt_bauhaus_combobox_set(g->combobox_patch, g->drawn_patch); g->patch = g->drawn_patch; self->gui_update(self); darktable.gui->reset = 0; self->request_color_pick = pick; // restore, the combobox will kill it } cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.)); cairo_set_source_rgb(cr, 1.0, 1.0, 1.0); cairo_rectangle(cr, width * besti / (float)cells_x + DT_PIXEL_APPLY_DPI(5), height * bestj / (float)cells_y + DT_PIXEL_APPLY_DPI(5), width / (float)cells_x - DT_PIXEL_APPLY_DPI(11), height / (float)cells_y - DT_PIXEL_APPLY_DPI(11)); cairo_stroke(cr); cairo_destroy(cr); cairo_set_source_surface(crf, cst, 0, 0); cairo_paint(crf); cairo_surface_destroy(cst); return TRUE; }
static void _make_bar_surface (ProgressBar *pProgressBar) { CairoDataRenderer *pRenderer = CAIRO_DATA_RENDERER (pProgressBar); int iWidth = pRenderer->iWidth; if (pProgressBar->cImageGradation != NULL) // an image is provided { pProgressBar->pBarSurface = cairo_dock_create_surface_from_image_simple ( pProgressBar->cImageGradation, iWidth, pProgressBar->iBarThickness); } if (pProgressBar->pBarSurface == NULL) // no image was provided, or it was not valid. { // create a surface to bufferize the pattern. pProgressBar->pBarSurface = cairo_dock_create_blank_surface (iWidth, pProgressBar->iBarThickness); cairo_t *ctx = cairo_create (pProgressBar->pBarSurface); cairo_pattern_t *pGradationPattern = NULL; if (myIndicatorsParam.bBarUseDefaultColors) { gldi_style_colors_set_selected_bg_color (ctx); } else { // create the pattern. pGradationPattern = cairo_pattern_create_linear (0., 0., iWidth, 0.); // de gauche a droite. g_return_if_fail (cairo_pattern_status (pGradationPattern) == CAIRO_STATUS_SUCCESS); cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE); gdouble *fColorGradation = pProgressBar->fColorGradation; int iNbColors = 2; int i; for (i = 0; i < iNbColors; i ++) { cairo_pattern_add_color_stop_rgba (pGradationPattern, (double)i / (iNbColors-1), fColorGradation[4*i+0], fColorGradation[4*i+1], fColorGradation[4*i+2], fColorGradation[4*i+3]); } cairo_set_source (ctx, pGradationPattern); } // draw the pattern on the surface. cairo_set_operator (ctx, CAIRO_OPERATOR_OVER); cairo_set_line_width (ctx, pProgressBar->iBarThickness); double r = .5*pProgressBar->iBarThickness; // radius cairo_move_to (ctx, 0, r); cairo_rel_line_to (ctx, iWidth, 0); cairo_stroke (ctx); if (pGradationPattern) cairo_pattern_destroy (pGradationPattern); cairo_destroy (ctx); } pProgressBar->iBarTexture = cairo_dock_create_texture_from_surface (pProgressBar->pBarSurface); }
static cairo_status_t twin_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font, unsigned long glyph, cairo_t *cr, cairo_text_extents_t *metrics) { double x1, y1, x2, y2, x3, y3; const int8_t *b = _cairo_twin_outlines + _cairo_twin_charmap[glyph >= ARRAY_LENGTH (_cairo_twin_charmap) ? 0 : glyph]; const int8_t *g = twin_glyph_draw(b); struct { cairo_bool_t snap; int snap_x; int snap_y; int n_snap_x; int n_snap_y; } info = {FALSE}; cairo_set_line_width (cr, 0.06); cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND); cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND); for (;;) { switch (*g++) { case 'M': cairo_close_path (cr); /* fall through */ case 'm': x1 = FX(*g++); y1 = FY(*g++); if (info.snap) { x1 = SNAPX (x1); y1 = SNAPY (y1); } cairo_move_to (cr, x1, y1); continue; case 'L': cairo_close_path (cr); /* fall through */ case 'l': x1 = FX(*g++); y1 = FY(*g++); if (info.snap) { x1 = SNAPX (x1); y1 = SNAPY (y1); } cairo_line_to (cr, x1, y1); continue; case 'C': cairo_close_path (cr); /* fall through */ case 'c': x1 = FX(*g++); y1 = FY(*g++); x2 = FX(*g++); y2 = FY(*g++); x3 = FX(*g++); y3 = FY(*g++); if (info.snap) { x1 = SNAPX (x1); y1 = SNAPY (y1); x2 = SNAPX (x2); y2 = SNAPY (y2); x3 = SNAPX (x3); y3 = SNAPY (y3); } cairo_curve_to (cr, x1, y1, x2, y2, x3, y3); continue; case 'E': cairo_close_path (cr); /* fall through */ case 'e': cairo_stroke (cr); break; case 'X': /* filler */ continue; } break; } metrics->x_advance = FX(twin_glyph_right(b)) + cairo_get_line_width (cr); metrics->x_advance += cairo_get_line_width (cr)/* XXX 2*x.margin */; if (info.snap) metrics->x_advance = SNAPI (SNAPX (metrics->x_advance)); return CAIRO_STATUS_SUCCESS; }
static void active_sensor_update_graph(ActiveSensor *as, cairo_t *cr) { GtkAllocation allocation; gdouble line_height; gdouble width, height; gdouble x, y; cairo_pattern_t *pattern; gint i; gtk_widget_get_allocation (as->graph, &allocation); width = allocation.width; height = allocation.height; /* so we can set a clipping area, as well as fill the * back of the graph black */ cairo_rectangle(cr, 0, 0, width, height); /* clip to rectangle and keep it as a path so can be * filled below */ cairo_clip_preserve(cr); /* use black for bg color of graphs */ cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); cairo_fill(cr); /* determine height to scale line at for each value - * only do as many as will fit or the number of * samples that we have */ for (i = 0; i < MIN(as->num_samples, width); i++) { /* need to remove one more to make it line up * properly when drawing */ x = width - i - 1; y = height; line_height = sensor_value_range_normalised(as->sensor_values[i], as->sensor_low_value, as->sensor_high_value) * height; if (line_height > 0) { cairo_move_to(cr, x, y); cairo_line_to(cr, x, y - line_height); } } /* make lines a gradient from slightly darker than * chosen color at bottom of graph, to slightly * lighter than chosen color at top of graph */ pattern = cairo_pattern_create_linear(x, y, x, 0); cairo_pattern_add_color_stop_rgb(pattern, 0, as->graph_color.red / 65535.0 - CAIRO_GRAPH_COLOR_GRADIENT, as->graph_color.green / 65535.0 - CAIRO_GRAPH_COLOR_GRADIENT, as->graph_color.blue / 65535.0 - CAIRO_GRAPH_COLOR_GRADIENT); cairo_pattern_add_color_stop_rgb(pattern, height, as->graph_color.red / 65535.0 + CAIRO_GRAPH_COLOR_GRADIENT, as->graph_color.green / 65535.0 + CAIRO_GRAPH_COLOR_GRADIENT, as->graph_color.blue / 65535.0 + CAIRO_GRAPH_COLOR_GRADIENT); cairo_set_source(cr, pattern); cairo_stroke(cr); cairo_pattern_destroy(pattern); }
/** * Draw the cursor on the canvas at the given position * insert_control is the last gap from the previous note except when the cursor is on a measure boundary in which case it is +1 or -1 to indicate where next inserted note will go. * minpixels is width of rectangle to draw indicating an object position (used when not a CHORD */ void draw_cursor (cairo_t * cr, DenemoMovement * si, gint xx, gint y, gint insert_control, gint minpixels, gint dclef) { if (!cr) return; gint height = calculateheight (si->cursor_y, dclef); gdouble scale = transition_cursor_scale (); cairo_save (cr); cairo_set_source_rgba (cr, 255 * (si->cursoroffend), (!si->cursoroffend) * (!si->cursor_appending) * 255, (!si->cursoroffend) * (si->cursor_appending) * 255, 0.7); if (si->cursor_appending) { cairo_rectangle (cr, xx - (si->cursoroffend ? CURSOR_WIDTH : 0), height + y - CURSOR_HEIGHT, 2 * CURSOR_WIDTH, 2 * CURSOR_HEIGHT); cairo_fill (cr); cairo_set_source_rgba (cr, 0, 0, 0,1); cairo_rectangle (cr, xx - (si->cursoroffend ? CURSOR_WIDTH : 0), height + y - CURSOR_HEIGHT, 2 * CURSOR_WIDTH, 2 * CURSOR_HEIGHT); cairo_stroke (cr); } else if (minpixels) { cairo_rectangle (cr, xx - CURSOR_WIDTH / 2, height + y - CURSOR_MINUS - CURSOR_HEIGHT / 2, minpixels, 2 * CURSOR_HEIGHT); cairo_fill (cr); cairo_set_line_width (cr, 2); cairo_set_source_rgba (cr, 0.6, 0.6, 0, 0.60); cairo_rectangle (cr, xx + - CURSOR_WIDTH / 2, y - CURSOR_HEIGHT * 2 , minpixels, STAFF_HEIGHT + CURSOR_HEIGHT * 4); cairo_stroke (cr); } else { cairo_rectangle (cr, xx - CURSOR_WIDTH / 2, height + y - CURSOR_MINUS - CURSOR_HEIGHT / 2, 2 * CURSOR_WIDTH, 2 * CURSOR_HEIGHT); cairo_fill (cr); cairo_set_source_rgba (cr, 0, 0, 0,1); cairo_rectangle (cr, xx - CURSOR_WIDTH / 2, height + y - CURSOR_MINUS - CURSOR_HEIGHT / 2, 2 * CURSOR_WIDTH, 2 * CURSOR_HEIGHT); cairo_stroke (cr); } { gdouble length = 20 / si->zoom; gdouble insert_pos = CURSOR_WIDTH * 0.8; if (!si->cursor_appending) { insert_pos = -insert_control / 4; } else if (si->cursoroffend) insert_pos = insert_control * CURSOR_WIDTH; static gboolean on; on = !on;//g_print (" %d and %x\n", gtk_widget_has_focus (gtk_widget_get_parent (Denemo.scorearea)), gtk_widget_get_state_flags (Denemo.scorearea)); //g_debug("on is %d %d\n", on, Denemo.prefs.cursor_highlight); if (((!Denemo.prefs.cursor_highlight) || (on && Denemo.prefs.cursor_highlight)) && (gtk_widget_has_focus (Denemo.scorearea) && gtk_widget_is_focus (Denemo.scorearea))) { cairo_set_source_rgb (cr, 0, 0, 255); cairo_set_line_width (cr, 4); cairo_move_to (cr, xx + insert_pos, y + 4); cairo_rel_line_to (cr, 0, STAFF_HEIGHT - 8); cairo_stroke (cr); //setcairocolor( cr, paintgc ); if (Denemo.project->view == DENEMO_PAGE_VIEW) { cairo_set_line_width (cr, 6.0 / si->zoom); cairo_set_source_rgba (cr, 0, 1, 0, 0.40); cairo_arc (cr, xx + CURSOR_WIDTH / 2, height + y, length, 0, 2 * M_PI); cairo_stroke (cr); } if(Denemo.project->audio_recording) highlight_audio_record(); } } cairo_restore (cr); /* Now draw ledgers if necessary and we're done */ draw_ledgers (cr, height, height, xx, y, CURSOR_WIDTH); }
/*********************************************** * do_glide_draw_arrow - * * A simple routine to draw a redmond style * arrow using the passed GC. * * Taken in part from smooth, it was based on * XFCE's & CleanIce draw arrow routines, * both which were based on ThinIce's. ***********************************************/ void do_glide_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_line_to(canvas, points[0].x + 0.5, points[0].y + 0.5); if (fill) { cairo_stroke_preserve(canvas); cairo_fill(canvas); } else { cairo_stroke(canvas); } cairo_restore(canvas); }
/*********************************************** * do_glide_draw_check - * * A simple routine to draw a redmond style * check mark using the passed Color. * * It originated in Smooth-Engine. ***********************************************/ void do_glide_draw_check (cairo_t *canvas, CairoColor * color, gint x, gint y, gint width, gint height) { /* EVEN - 0 1 2 3 4 5 6 7 8 9 +---+---+---+---+---+---+---+---+---+---+ 0 | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+ 1 | | | | | | | | | x | | +---+---+---+---+---+---+---+---+---+---+ 2 | | | | | | | | x | x | | +---+---+---+---+---+---+---+---+---+---+ 3 | | | | | | | x | x | x | | +---+---+---+---+---+---+---+---+---+---+ 4 | | x | | | | x | x | x | | | +---+---+---+---+---+---+---+---+---+---+ 5 | | x | x | | x | x | x | | | | +---+---+---+---+---+---+---+---+---+---+ 6 | | x | x | x | x | x | | | | | +---+---+---+---+---+---+---+---+---+---+ 7 | | | x | x | x | | | | | | +---+---+---+---+---+---+---+---+---+---+ 8 | | | | x | | | | | | | +---+---+---+---+---+---+---+---+---+---+ 9 | | | | | | | | | | | +---+---+---+---+---+---+---+---+---+---+ ODD - 0 1 2 3 4 5 6 7 8 +---+---+---+---+---+---+---+---+---+ 0 | | | | | | | | | | +---+---+---+---+---+---+---+---+---+ 1 | | | | | | | | x | | +---+---+---+---+---+---+---+---+---+ 2 | | | | | | | x | x | | +---+---+---+---+---+---+---+---+---+ 3 | | x | | | | x | x | x | | +---+---+---+---+---+---+---+---+---+ 4 | | x | x | | x | x | x | | | +---+---+---+---+---+---+---+---+---+ 5 | | x | x | x | x | x | | | | +---+---+---+---+---+---+---+---+---+ 6 | | | x | x | x | | | | | +---+---+---+---+---+---+---+---+---+ 7 | | | | x | | | | | | +---+---+---+---+---+---+---+---+---+ 8 | | | | | | | | | | +---+---+---+---+---+---+---+---+---+ */ gint odd = 0; gdouble left, top; gint scale, factor; scale = MIN(width, height); factor = 10; if ((odd = (scale % 2))) { factor -= 1; } if (scale <= (factor + 2)) scale = factor; left = x + floor((width - scale) / 2) + 0.5; top = y + floor((height - scale) / 2) + 0.5; cairo_save(canvas); ge_cairo_set_color(canvas, color); cairo_set_line_width(canvas, 0.5); cairo_move_to(canvas, left + floor((1*scale)/factor), top + floor(((4-odd)*scale)/factor)); /*(1,4-odd)*/ cairo_line_to(canvas, left + floor((1*scale)/factor), top + floor(((6-odd)*scale)/factor)); /*(1,6-odd)*/ cairo_line_to(canvas, left + floor((3*scale)/factor), top + floor(((8-odd)*scale)/factor)); /*(3,8-odd)*/ cairo_line_to(canvas, left + floor(((8-odd)*scale)/factor), top + floor((3*scale)/factor)); /*(8-odd,3)*/ cairo_line_to(canvas, left + floor(((8-odd)*scale)/factor), top + floor((1*scale)/factor)); /*(8-odd,1)*/ cairo_line_to(canvas, left + floor((3*scale)/factor), top + floor(((6-odd)*scale)/factor)); /*(3,6-odd)*/ cairo_line_to(canvas, left + floor((1*scale)/factor), top + floor(((4-odd)*scale)/factor)); /*(1,4-odd)*/ cairo_fill_preserve(canvas); cairo_stroke(canvas); cairo_restore(canvas); }
void GraphicsContext::strokeArc(const IntRect& rect, int startAngle, int angleSpan) { if (paintingDisabled() || strokeStyle() == NoStroke) return; int x = rect.x(); int y = rect.y(); float w = rect.width(); float h = rect.height(); float scaleFactor = h / w; float reverseScaleFactor = w / h; float hRadius = w / 2; float vRadius = h / 2; float fa = startAngle; float falen = fa + angleSpan; cairo_t* cr = m_data->cr; cairo_save(cr); if (w != h) cairo_scale(cr, 1., scaleFactor); cairo_arc_negative(cr, x + hRadius, (y + vRadius) * reverseScaleFactor, hRadius, -fa * M_PI/180, -falen * M_PI/180); if (w != h) cairo_scale(cr, 1., reverseScaleFactor); float width = strokeThickness(); int patWidth = 0; switch (strokeStyle()) { case DottedStroke: patWidth = static_cast<int>(width / 2); break; case DashedStroke: patWidth = 3 * static_cast<int>(width / 2); break; default: break; } setColor(cr, strokeColor()); if (patWidth) { // Example: 80 pixels with a width of 30 pixels. // Remainder is 20. The maximum pixels of line we could paint // will be 50 pixels. int distance; if (hRadius == vRadius) distance = static_cast<int>((M_PI * hRadius) / 2.0); else // We are elliptical and will have to estimate the distance distance = static_cast<int>((M_PI * sqrtf((hRadius * hRadius + vRadius * vRadius) / 2.0)) / 2.0); int remainder = distance % patWidth; int coverage = distance - remainder; int numSegments = coverage / patWidth; float patternOffset = 0.0; // Special case 1px dotted borders for speed. if (patWidth == 1) patternOffset = 1.0; else { bool evenNumberOfSegments = numSegments % 2 == 0; if (remainder) evenNumberOfSegments = !evenNumberOfSegments; if (evenNumberOfSegments) { if (remainder) { patternOffset += patWidth - remainder; patternOffset += remainder / 2.0; } else patternOffset = patWidth / 2.0; } else { if (remainder) patternOffset = (patWidth - remainder) / 2.0; } } double dash = patWidth; cairo_set_dash(cr, &dash, 1, patternOffset); } cairo_stroke(cr); cairo_restore(cr); }
/* The marker is drawn with cairo. It is composed of 1 static filled circle * and 1 stroked circle animated as an echo. */ static ClutterActor * create_marker () { ClutterActor *marker; ClutterActor *bg; ClutterTimeline *timeline; cairo_t *cr; /* Create the marker */ marker = champlain_custom_marker_new (); /* Static filled circle ----------------------------------------------- */ bg = clutter_cairo_texture_new (MARKER_SIZE, MARKER_SIZE); cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (bg)); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint(cr); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); /* Draw the circle */ cairo_set_source_rgb (cr, 0, 0, 0); cairo_arc (cr, MARKER_SIZE / 2.0, MARKER_SIZE / 2.0, MARKER_SIZE / 2.0, 0, 2 * M_PI); cairo_close_path (cr); /* Fill the circle */ cairo_set_source_rgba (cr, 0.1, 0.1, 0.9, 1.0); cairo_fill (cr); cairo_destroy (cr); /* Add the circle to the marker */ clutter_container_add_actor (CLUTTER_CONTAINER (marker), bg); clutter_actor_set_anchor_point_from_gravity (bg, CLUTTER_GRAVITY_CENTER); clutter_actor_set_position (bg, 0, 0); /* Echo circle -------------------------------------------------------- */ bg = clutter_cairo_texture_new (2 * MARKER_SIZE, 2 * MARKER_SIZE); cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (bg)); /* Draw the circle */ cairo_set_source_rgb (cr, 0, 0, 0); cairo_arc (cr, MARKER_SIZE, MARKER_SIZE, 0.9 * MARKER_SIZE, 0, 2 * M_PI); cairo_close_path (cr); /* Stroke the circle */ cairo_set_line_width (cr, 2.0); cairo_set_source_rgba (cr, 0.1, 0.1, 0.7, 1.0); cairo_stroke (cr); cairo_destroy (cr); /* Add the circle to the marker */ clutter_container_add_actor (CLUTTER_CONTAINER (marker), bg); clutter_actor_lower_bottom (bg); /* Ensure it is under the previous circle */ clutter_actor_set_position (bg, 0, 0); clutter_actor_set_anchor_point_from_gravity (bg, CLUTTER_GRAVITY_CENTER); /* Animate the echo circle */ timeline = clutter_timeline_new (1000); clutter_timeline_set_loop (timeline, TRUE); clutter_actor_set_opacity (CLUTTER_ACTOR (bg), 255); clutter_actor_set_scale (CLUTTER_ACTOR (bg), 0.5, 0.5); clutter_actor_animate_with_timeline (CLUTTER_ACTOR (bg), CLUTTER_EASE_OUT_SINE, timeline, "opacity", 0, "scale-x", 2.0, "scale-y", 2.0, NULL); clutter_timeline_start (timeline); return marker; }
static gboolean dt_iop_levels_area_draw(GtkWidget *widget, cairo_t *crf, 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; dt_develop_t *dev = darktable.develop; const int inset = DT_GUI_CURVE_EDITOR_INSET; GtkAllocation allocation; gtk_widget_get_allocation(GTK_WIDGET(c->area), &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); 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 != DT_REQUEST_COLORPICK_OFF && self->color_picker_point[0] >= 0.0f && self->color_picker_point[1] >= 0.0f && self->picked_color_max[0] >= 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, DT_PIXEL_APPLY_DPI(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, DT_PIXEL_APPLY_DPI(.4)); cairo_set_source_rgb(cr, .1, .1, .1); if(dev->histogram_type == DT_DEV_HISTOGRAM_WAVEFORM) dt_draw_waveform_lines(cr, 0, 0, width, height); else dt_draw_vertical_lines(cr, 4, 0, 0, width, height); // Drawing the vertical line indicators cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(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, DT_PIXEL_APPLY_DPI(1.)); const float arrw = DT_PIXEL_APPLY_DPI(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) { uint32_t *hist = self->histogram; float hist_max = dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR ? self->histogram_max[0] : logf(1.0 + self->histogram_max[0]); if(hist && hist_max > 0.0f) { cairo_save(cr); cairo_scale(cr, width / 63.0, -(height - DT_PIXEL_APPLY_DPI(5)) / hist_max); cairo_set_source_rgba(cr, .2, .2, .2, 0.5); dt_draw_histogram_8(cr, hist, 0, dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR); // TODO: make draw // handle waveform // histograms cairo_restore(cr); } } // Cleaning up cairo_destroy(cr); cairo_set_source_surface(crf, cst, 0, 0); cairo_paint(crf); cairo_surface_destroy(cst); return TRUE; }
/** draw frequency calibration circles * and on screen annotations - sample-rate dependent */ static void update_grid(MF2UI* ui) { const double ccc = ui->width / 2.0 + .5; const double rad = (ui->width - XOFF) * .5; cairo_t *cr = cairo_create (ui->sf_ann); cairo_rectangle (cr, 0, 0, ui->width, ui->height); CairoSetSouerceRGBA(ui->c_bg); cairo_fill (cr); cairo_set_line_width (cr, 1.0); cairo_arc (cr, ccc, ccc, rad, 0, 2.0 * M_PI); cairo_set_source_rgba(cr, 0, 0, 0, 1.0); cairo_fill_preserve(cr); CairoSetSouerceRGBA(c_g90); cairo_stroke(cr); const double dash1[] = {1.0, 2.0}; cairo_set_dash(cr, dash1, 2, 0); CairoSetSouerceRGBA(c_grd); float freq = 62.5; while (freq < ui->rate / 2) { char txt[16]; if (freq < 1000) { snprintf(txt, 16, "%d Hz", (int)ceil(freq)); } else { snprintf(txt, 16, "%d KHz", (int)ceil(freq/1000.f)); } { const float dr = ui->scale * PH_RAD * fast_log10(1.0 + 2 * freq * ui->log_rate / ui->rate) / ui->log_base; cairo_arc (cr, ccc, ccc, dr, 0, 2.0 * M_PI); cairo_stroke(cr); const float px = ccc + dr * sinf(M_PI * -.75); const float py = ccc - dr * cosf(M_PI * -.75); write_text_full(cr, txt, ui->font[0], px, py, M_PI * -.75, -2, c_ahz); } freq *= 2.0; } const double dash2[] = {1.0, 3.0}; cairo_set_line_width(cr, 3.5); cairo_set_dash(cr, dash2, 2, 2); cairo_set_line_width(cr, 1.5); cairo_move_to(cr, ccc - rad, ccc); cairo_line_to(cr, ccc + rad, ccc); cairo_stroke(cr); cairo_set_line_width(cr, 3.5); cairo_move_to(cr, ccc, ccc - rad); cairo_line_to(cr, ccc, ccc + rad); cairo_stroke(cr); cairo_set_dash(cr, NULL, 0, 0); write_text_full(cr, "+L", ui->font[0], ccc, ccc - rad * .92, 0, -2, c_ann); write_text_full(cr, "-L", ui->font[0], ccc, ccc + rad * .92, 0, -2, c_ann); write_text_full(cr, "0\u00B0", ui->font[0], ccc, ccc - rad * .80, 0, -2, c_ann); write_text_full(cr, "180\u00B0", ui->font[0], ccc, ccc + rad * .80, 0, -2, c_ann); write_text_full(cr, "-R", ui->font[0], ccc - rad * .92, ccc, 0, -2, c_ann); write_text_full(cr, "+R", ui->font[0], ccc + rad * .92, ccc, 0, -2, c_ann); write_text_full(cr, "-90\u00B0", ui->font[0], ccc - rad * .80, ccc, 0, -2, c_ann); write_text_full(cr, "+90\u00B0", ui->font[0], ccc + rad * .80, ccc, 0, -2, c_ann); cairo_destroy (cr); }
static gboolean dt_iop_levels_area_draw(GtkWidget *widget, cairo_t *crf, 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; dt_develop_t *dev = darktable.develop; const int inset = DT_GUI_CURVE_EDITOR_INSET; GtkAllocation allocation; gtk_widget_get_allocation(GTK_WIDGET(c->area), &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 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, DT_PIXEL_APPLY_DPI(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, DT_PIXEL_APPLY_DPI(.4)); cairo_set_source_rgb(cr, .1, .1, .1); if(dev->histogram_type == DT_DEV_HISTOGRAM_WAVEFORM) dt_draw_waveform_lines(cr, 0, 0, width, height); else dt_draw_vertical_lines(cr, 4, 0, 0, width, height); // Drawing the vertical line indicators cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(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, DT_PIXEL_APPLY_DPI(1.)); const float arrw = DT_PIXEL_APPLY_DPI(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) { uint32_t *hist = self->histogram; float hist_max = dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR ? self->histogram_max[0] : logf(1.0 + self->histogram_max[0]); if(hist && hist_max > 0.0f) { cairo_save(cr); cairo_scale(cr, width / 255.0, -(height - DT_PIXEL_APPLY_DPI(5)) / hist_max); cairo_set_source_rgba(cr, .2, .2, .2, 0.5); dt_draw_histogram_8(cr, hist, 4, 0, dev->histogram_type == DT_DEV_HISTOGRAM_LINEAR); // TODO: make draw // handle waveform // histograms cairo_restore(cr); } } // Cleaning up cairo_destroy(cr); cairo_set_source_surface(crf, cst, 0, 0); cairo_paint(crf); cairo_surface_destroy(cst); return TRUE; }
/** draw level-range display * depends on gain (dial) and cutoff */ static void update_annotations(MF2UI* ui) { cairo_t* cr = cairo_create (ui->sf_gain); cairo_rectangle (cr, 0, 0, ANN_W, 40); CairoSetSouerceRGBA(ui->c_bg); cairo_fill (cr); rounded_rectangle (cr, 3, 3 , ANN_W - 6, ANN_H - 6, 6); if (ui->drag_cutoff_x >= 0 || ui->prelight_cutoff) { cairo_set_source_rgba(cr, .15, .15, .15, 1.0); } else { cairo_set_source_rgba(cr, .0, .0, .0, 1.0); } cairo_fill (cr); cairo_set_line_width (cr, 1.0); const uint32_t mxw = ANN_W - XOFF * 2 - 36; const uint32_t mxo = XOFF + 18; const float cutoff = ui->db_cutoff; const uint32_t cutoff_m = floor(mxw * (MIN_CUTOFF - cutoff) / MIN_CUTOFF); assert(cutoff_m < mxw); const uint32_t cutoff_w = mxw - cutoff_m; for (uint32_t i=0; i < mxw; ++i) { float clr[3]; if (i < cutoff_m) { clr[0] = clr[1] = clr[2] = .1; } else { const float pk = (i-cutoff_m) / (float)cutoff_w; hsl2rgb(clr, .68 - .72 * pk, .9, .2 + pk * .4); } cairo_set_source_rgba(cr, clr[0], clr[1], clr[2], 1.0); cairo_move_to(cr, mxo + i + .5, ANN_B - 5); cairo_line_to(cr, mxo + i + .5, ANN_B); cairo_stroke(cr); } cairo_set_source_rgba(cr, .8, .8, .8, .8); const float gain = robtk_dial_get_value(ui->gain); for (int32_t db = MIN_CUTOFF; db <=0 ; db+= 10) { char dbt[16]; if (db == 0) { snprintf(dbt, 16, "\u2265%+.0fdB", (db - gain)); } else { snprintf(dbt, 16, "%+.0fdB", (db - gain)); } write_text_full(cr, dbt, ui->font[0], mxo + rint(mxw * (-MIN_CUTOFF + db) / -MIN_CUTOFF), ANN_B - 14 , 0, 2, c_wht); cairo_move_to(cr, mxo + rint(mxw * (-MIN_CUTOFF + db) / -MIN_CUTOFF) + .5, ANN_B - 7); cairo_line_to(cr, mxo + rint(mxw * (-MIN_CUTOFF + db) / -MIN_CUTOFF) + .5, ANN_B); cairo_stroke(cr); } /* black overlay above low-end cutoff */ if (ui->db_cutoff > MIN_CUTOFF && (ui->drag_cutoff_x >= 0 || ui->prelight_cutoff)) { const float cox = rint(mxw * (ui->db_cutoff - MIN_CUTOFF)/ -MIN_CUTOFF); cairo_rectangle(cr, mxo, 6, cox, ANN_B - 6); cairo_set_source_rgba(cr, .0, .0, .0, .7); cairo_fill(cr); cairo_set_line_width (cr, 1.0); cairo_set_source_rgba(cr, .9, .5, .5, .6); cairo_move_to(cr, mxo + cox + .5, ANN_B - 6); cairo_line_to(cr, mxo + cox + .5, ANN_B + 1); cairo_stroke(cr); } cairo_destroy (cr); }
static void schgui_cairo_path_draw(SchGUICairoDrawItem *item, cairo_t *cairo) { if (cairo != NULL) { SchGUICairoPathPrivate *privat = SCHGUI_CAIRO_PATH_GET_PRIVATE(item); if (privat != NULL) { GSList *node; SchPathCommand *command; cairo_set_source_rgba(cairo, privat->red, privat->green, privat->blue, privat->alpha); cairo_set_line_width(cairo, privat->line_width); node = privat->commands; while (node != NULL) { command = SCH_PATH_COMMAND(node->data); switch (command->type) { case SCH_PATH_COMMAND_INVALID: g_debug("SchGUICairoPath: invalid path command"); break; case SCH_PATH_COMMAND_CLOSEPATH: cairo_close_path(cairo); break; case SCH_PATH_COMMAND_CURVETO_ABS: cairo_curve_to( cairo, command->curveto.x[0], command->curveto.y[0], command->curveto.x[1], command->curveto.y[1], command->curveto.x[2], command->curveto.y[2] ); break; case SCH_PATH_COMMAND_CURVETO_REL: cairo_rel_curve_to( cairo, command->curveto.x[0], command->curveto.y[0], command->curveto.x[1], command->curveto.y[1], command->curveto.x[2], command->curveto.y[2] ); break; case SCH_PATH_COMMAND_LINETO_ABS: cairo_line_to(cairo, command->lineto.x, command->lineto.y); break; case SCH_PATH_COMMAND_LINETO_REL: cairo_rel_line_to(cairo, command->lineto.x, command->lineto.y); break; case SCH_PATH_COMMAND_MOVETO_ABS: cairo_move_to(cairo, command->moveto.x, command->moveto.y); break; case SCH_PATH_COMMAND_MOVETO_REL: cairo_rel_move_to(cairo, command->moveto.x, command->moveto.y); break; default: g_debug("SchGUICairoPath: unknown path command"); } node = g_slist_next(node); } if (privat->solid) { cairo_fill_preserve(cairo); } cairo_stroke(cairo); } } }
/* stereo-phase correlation display */ static bool pc_expose_event(RobWidget* handle, cairo_t* cr, cairo_rectangle_t *ev) { MF2UI* ui = (MF2UI*)GET_HANDLE(handle); if (!ui->sf_nfo && ui->nfo) { PangoFontDescription *fd = pango_font_description_from_string("Sans 10px"); create_text_surface2(&ui->sf_nfo, 12, PC_BOUNDH, 0, PC_TOP, ui->nfo, fd, M_PI * -.5, 7, c_g60); pango_font_description_free(fd); } cairo_save(cr); cairo_translate(cr, 0, rint((ui->m0_height - ui->height) * .5)); cairo_rectangle (cr, ev->x, ev->y, ev->width, ev->height); cairo_clip (cr); /* display phase-correlation */ cairo_set_operator (cr, CAIRO_OPERATOR_OVER); /* PC meter backgroud */ CairoSetSouerceRGBA(ui->c_bg); cairo_rectangle (cr, 0, 0, PC_BOUNDW, PC_BOUNDH); cairo_fill(cr); CairoSetSouerceRGBA(c_blk); cairo_set_line_width(cr, 1.0); rounded_rectangle (cr, PC_LEFT-1, PC_TOP + 1.0, PC_WIDTH+2, PC_HEIGHT - 2.0, 3); cairo_fill_preserve(cr); cairo_save(cr); cairo_clip(cr); /* value */ CairoSetSouerceRGBA(c_glb); const float c = rintf(PC_TOP + PC_BLOCKSIZE * ui->cor); rounded_rectangle (cr, PC_LEFT, c, PC_WIDTH, PC_BLOCK, 4); cairo_fill(cr); /* labels w/ background */ cairo_set_source_surface(cr, ui->sf_pc[0], PC_LEFT, PC_TOP + 5); cairo_paint (cr); cairo_set_source_surface(cr, ui->sf_pc[1], PC_LEFT, PC_TOP + PC_HEIGHT - 25); cairo_paint (cr); cairo_restore(cr); rounded_rectangle (cr, PC_LEFT - .5, PC_TOP + .5, PC_WIDTH + 1, PC_HEIGHT - 1, 3); CairoSetSouerceRGBA(c_g90); cairo_stroke(cr); /* annotations */ cairo_set_operator (cr, CAIRO_OPERATOR_SCREEN); CairoSetSouerceRGBA(c_grd); cairo_set_line_width(cr, 1.0); #define PC_ANNOTATION(YPOS, OFF) \ cairo_move_to(cr, PC_LEFT + OFF, rintf(PC_TOP + YPOS) + 0.5); \ cairo_line_to(cr, PC_LEFT + PC_WIDTH - OFF, rintf(PC_TOP + YPOS) + 0.5);\ cairo_stroke(cr); PC_ANNOTATION(PC_HEIGHT * 0.1, 4.0); PC_ANNOTATION(PC_HEIGHT * 0.2, 4.0); PC_ANNOTATION(PC_HEIGHT * 0.3, 4.0); PC_ANNOTATION(PC_HEIGHT * 0.4, 4.0); PC_ANNOTATION(PC_HEIGHT * 0.6, 4.0); PC_ANNOTATION(PC_HEIGHT * 0.7, 4.0); PC_ANNOTATION(PC_HEIGHT * 0.8, 4.0); PC_ANNOTATION(PC_HEIGHT * 0.9, 4.0); CairoSetSouerceRGBA(c_glr); cairo_set_line_width(cr, 1.5); PC_ANNOTATION(PC_HEIGHT * 0.5, 1.5); cairo_restore(cr); if (ui->sf_nfo) { cairo_rectangle (cr, ev->x, ev->y, ev->width, ev->height); cairo_clip (cr); cairo_set_source_surface(cr, ui->sf_nfo, PC_BOUNDW - 14, 0); cairo_paint (cr); } return TRUE; }
/* expose snapshot over center viewport */ void gui_post_expose(dt_lib_module_t *self, cairo_t *cri, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { dt_lib_snapshots_t *d = (dt_lib_snapshots_t *)self->data; // convert to image coordinates: const int32_t capwd = darktable.thumbnail_width; const int32_t capht = darktable.thumbnail_height; const int32_t width_i = d->vp_width; const int32_t height_i = d->vp_height; if(width_i > capwd) pointerx += (capwd-width_i) *.5f; if(height_i > capht) pointery += (capht-height_i)*.5f; if(d->snapshot_image) { d->vp_width = width; d->vp_height = height; /* check if mouse pointer is on draggable area */ double xp = pointerx/d->vp_width; double yp = pointery/d->vp_height; double xpt = xp*0.01; double ypt = yp*0.01; gboolean mouse_over_control = d->vertical ? ((xp > d->vp_xpointer-xpt && xp < d->vp_xpointer+xpt)?TRUE:FALSE) : ((yp > d->vp_ypointer-ypt && yp < d->vp_ypointer+ypt)?TRUE:FALSE); /* set x,y,w,h of surface depending on split align and invert */ double x = d->vertical ? (d->inverted?width*d->vp_xpointer:0) : 0; double y = d->vertical ? 0 : (d->inverted?height*d->vp_ypointer:0); double w = d->vertical ? (d->inverted?(width * (1.0 - d->vp_xpointer)):width * d->vp_xpointer) : width; double h = d->vertical ? height : (d->inverted?(height * (1.0 - d->vp_ypointer)):height * d->vp_ypointer); cairo_set_source_surface(cri, d->snapshot_image, 0, 0); //cairo_rectangle(cri, 0, 0, width*d->vp_xpointer, height); cairo_rectangle(cri,x,y,w,h); cairo_fill(cri); /* draw the split line */ cairo_set_source_rgb(cri, .7, .7, .7); cairo_set_line_width(cri, (mouse_over_control ? 2.0 : 0.5) ); if(d->vertical) { cairo_move_to(cri, width*d->vp_xpointer, 0.0f); cairo_line_to(cri, width*d->vp_xpointer, height); } else { cairo_move_to(cri, 0.0f, height*d->vp_ypointer); cairo_line_to(cri, width, height*d->vp_ypointer); } cairo_stroke(cri); /* if mouse over control lets draw center rotate control, hide if split is dragged */ if(!d->dragging && mouse_over_control) { cairo_set_line_width(cri,0.5); double s = width*HANDLE_SIZE; dtgtk_cairo_paint_refresh(cri, (d->vertical ? width*d->vp_xpointer : width*0.5)-(s*0.5), (d->vertical ? height*0.5 : height*d->vp_ypointer)-(s*0.5), s,s,d->vertical?1:0); } } }
static void plot_profile(struct dive *dive, cairo_t *cr, double topx, double topy, double maxx, double maxy) { double scalex, scaley; int begins, sec, depth; int i, samples; struct sample *sample; int maxtime, maxdepth; samples = dive->samples; if (!samples) return; cairo_set_line_width(cr, 2); /* Get plot scaling limits */ maxtime = round_seconds_up(dive->duration.seconds); maxdepth = round_feet_up(to_feet(dive->maxdepth)); /* Time markers: every 5 min */ scalex = maxtime; scaley = 1.0; for (i = 5*60; i < maxtime; i += 5*60) { cairo_move_to(cr, SCALE(i, 0)); cairo_line_to(cr, SCALE(i, 1)); } /* Depth markers: every 15 ft */ scalex = 1.0; scaley = maxdepth; cairo_set_source_rgba(cr, 1, 1, 1, 0.5); for (i = 15; i < maxdepth; i += 15) { cairo_move_to(cr, SCALE(0, i)); cairo_line_to(cr, SCALE(1, i)); } cairo_stroke(cr); /* Show mean depth */ cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.40); cairo_move_to(cr, SCALE(0, to_feet(dive->meandepth))); cairo_line_to(cr, SCALE(1, to_feet(dive->meandepth))); cairo_stroke(cr); scalex = maxtime; sample = dive->sample; cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.80); begins = sample->time.seconds; cairo_move_to(cr, SCALE(sample->time.seconds, to_feet(sample->depth))); for (i = 1; i < dive->samples; i++) { sample++; sec = sample->time.seconds; depth = to_feet(sample->depth); cairo_line_to(cr, SCALE(sec, depth)); } scaley = 1.0; cairo_line_to(cr, SCALE(sec, 0)); cairo_line_to(cr, SCALE(begins, 0)); cairo_close_path(cr); cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.20); cairo_fill_preserve(cr); cairo_set_source_rgba(cr, 1, 0.2, 0.2, 0.80); cairo_stroke(cr); }
void plot_gradient_bar(cairo_t * cairo_context, double origin_x, double origin_y, double size_x, double size_y, double min_value, double max_value, const char * measure_unit_str, int vertical_flag) { cairo_pattern_t * linear; size_t idx; char label_min[20], label_max[20]; cairo_text_extents_t min_te, max_te; double bar_origin_x, bar_origin_y; double bar_size_x, bar_size_y; const double text_margin_factor = 1.1; const double tick_height = 6.0; if(measure_unit_str != NULL && measure_unit_str[0] != '\0') { sprintf(label_min, "%.4g %s", min_value, measure_unit_str); sprintf(label_max, "%.4g %s", max_value, measure_unit_str); } else { sprintf(label_min, "%.4g", min_value); sprintf(label_max, "%.4g", max_value); } cairo_text_extents (cairo_context, label_min, &min_te); cairo_text_extents (cairo_context, label_max, &max_te); bar_origin_x = origin_x; bar_origin_y = origin_y; bar_size_x = size_x; bar_size_y = size_y; /* If zero is within the range, plot a small thick around it */ if(max_value > 0.0 && min_value < 0.0) { double zero_pos = origin_x + size_x * (0.0 - min_value) / (max_value - min_value); cairo_move_to(cairo_context, zero_pos, origin_y); cairo_line_to(cairo_context, zero_pos, origin_y + size_y); cairo_set_source_rgb(cairo_context, 0.0, 0.0, 0.0); cairo_stroke(cairo_context); } /* Now plot the gradient */ if(vertical_flag) { size_x -= MAX(min_te.width, max_te.width) * text_margin_factor; linear = cairo_pattern_create_linear (0.0, bar_origin_y, 0.0, bar_origin_y + bar_size_y); } else { bar_origin_x += min_te.width * text_margin_factor; bar_size_x -= (min_te.width + max_te.width) * text_margin_factor; linear = cairo_pattern_create_linear (bar_origin_x, 0.0, bar_origin_x + bar_size_x, 0.0); } for(idx = 0; idx < num_of_levels; ++idx) { cairo_pattern_add_color_stop_rgb(linear, levels[idx], colors[idx].red, colors[idx].green, colors[idx].blue); } cairo_rectangle(cairo_context, bar_origin_x, bar_origin_y + tick_height, bar_size_x, bar_size_y - 2 * tick_height); /* Draw the gradient */ cairo_set_source(cairo_context, linear); cairo_fill_preserve(cairo_context); cairo_pattern_destroy(linear); /* Draw the border */ cairo_set_source_rgb(cairo_context, 0.0, 0.0, 0.0); cairo_stroke(cairo_context); /* Draw the labels */ { double baseline = origin_y + size_y * 0.5 - min_te.y_bearing - min_te.height * 0.5; cairo_move_to(cairo_context, origin_x, baseline); cairo_show_text(cairo_context, label_min); baseline = origin_y + size_y * 0.5 - max_te.y_bearing - max_te.height * 0.5; cairo_move_to(cairo_context, origin_x + size_x - max_te.width, baseline); cairo_show_text(cairo_context, label_max); } }
static void dt_circle_events_post_expose(cairo_t *cr, float zoom_scale, dt_masks_form_gui_t *gui, int index) { double dashed[] = { 4.0, 4.0 }; dashed[0] /= zoom_scale; dashed[1] /= zoom_scale; int len = sizeof(dashed) / sizeof(dashed[0]); dt_masks_form_gui_points_t *gpt = (dt_masks_form_gui_points_t *)g_list_nth_data(gui->points, index); // add a preview when creating a circle // in creation mode if(gui->creation) { float wd = darktable.develop->preview_pipe->iwidth; float ht = darktable.develop->preview_pipe->iheight; if(gui->guipoints_count == 0) { dt_masks_form_t *form = darktable.develop->form_visible; if(!form) return; float radius1, radius2; if(form->type & (DT_MASKS_CLONE | DT_MASKS_NON_CLONE)) { radius1 = dt_conf_get_sanitize_set("plugins/darkroom/spots/circle_size", 0.001f, 0.5f); radius2 = dt_conf_get_sanitize_set("plugins/darkroom/spots/circle_border", 0.0005f, 0.5f); } else { radius1 = dt_conf_get_sanitize_set("plugins/darkroom/masks/circle/size", 0.001f, 0.5f); radius2 = dt_conf_get_sanitize_set("plugins/darkroom/masks/circle/border", 0.0005f, 0.5f); } radius2 += radius1; radius1 *= MIN(wd, ht); radius2 *= MIN(wd, ht); float xpos, ypos; if((gui->posx == -1.f && gui->posy == -1.f) || gui->mouse_leaved_center) { const float zoom_x = dt_control_get_dev_zoom_x(); const float zoom_y = dt_control_get_dev_zoom_y(); xpos = (.5f + zoom_x) * darktable.develop->preview_pipe->backbuf_width; ypos = (.5f + zoom_y) * darktable.develop->preview_pipe->backbuf_height; } else { xpos = gui->posx; ypos = gui->posy; } cairo_save(cr); // draw circle cairo_set_dash(cr, dashed, 0, 0); cairo_set_line_width(cr, 3.0 / zoom_scale); cairo_set_source_rgba(cr, .3, .3, .3, .8); cairo_arc(cr, xpos, ypos, radius1, 0, 2.0 * M_PI); cairo_stroke_preserve(cr); cairo_set_line_width(cr, 1.0 / zoom_scale); cairo_set_source_rgba(cr, .8, .8, .8, .8); cairo_stroke(cr); // draw border cairo_set_dash(cr, dashed, len, 0); cairo_set_line_width(cr, 1.0 / zoom_scale); cairo_set_source_rgba(cr, .3, .3, .3, .8); cairo_arc(cr, xpos, ypos, radius2, 0, 2.0 * M_PI); cairo_stroke_preserve(cr); cairo_set_line_width(cr, 1.0 / zoom_scale); cairo_set_source_rgba(cr, .8, .8, .8, .8); cairo_set_dash(cr, dashed, len, 4); cairo_stroke(cr); // draw a cross where the source will be created if(form->type & DT_MASKS_CLONE) { float x = 0.f, y = 0.f; dt_masks_calculate_source_pos_value(gui, DT_MASKS_CIRCLE, xpos, ypos, xpos, ypos, &x, &y, FALSE); dt_masks_draw_clone_source_pos(cr, zoom_scale, x, y); } cairo_restore(cr); } return; } if(!gpt) return; float dx = 0, dy = 0, dxs = 0, dys = 0; if((gui->group_selected == index) && gui->form_dragging) { dx = gui->posx + gui->dx - gpt->points[0]; dy = gui->posy + gui->dy - gpt->points[1]; } if((gui->group_selected == index) && gui->source_dragging) { dxs = gui->posx + gui->dx - gpt->source[0]; dys = gui->posy + gui->dy - gpt->source[1]; } if(gpt->points_count > 6) { cairo_set_dash(cr, dashed, 0, 0); if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 5.0 / zoom_scale); else cairo_set_line_width(cr, 3.0 / zoom_scale); cairo_set_source_rgba(cr, .3, .3, .3, .8); cairo_move_to(cr, gpt->points[2] + dx, gpt->points[3] + dy); for(int i = 2; i < gpt->points_count; i++) { cairo_line_to(cr, gpt->points[i * 2] + dx, gpt->points[i * 2 + 1] + dy); } cairo_line_to(cr, gpt->points[2] + dx, gpt->points[3] + dy); cairo_stroke_preserve(cr); if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 2.0 / zoom_scale); else cairo_set_line_width(cr, 1.0 / zoom_scale); cairo_set_source_rgba(cr, .8, .8, .8, .8); cairo_stroke(cr); } // draw border if((gui->group_selected == index) && gpt->border_count > 6) { cairo_set_dash(cr, dashed, len, 0); if((gui->group_selected == index) && (gui->border_selected)) cairo_set_line_width(cr, 2.0 / zoom_scale); else cairo_set_line_width(cr, 1.0 / zoom_scale); cairo_set_source_rgba(cr, .3, .3, .3, .8); cairo_move_to(cr, gpt->border[2] + dx, gpt->border[3] + dy); for(int i = 2; i < gpt->border_count; i++) { cairo_line_to(cr, gpt->border[i * 2] + dx, gpt->border[i * 2 + 1] + dy); } cairo_line_to(cr, gpt->border[2] + dx, gpt->border[3] + dy); cairo_stroke_preserve(cr); if((gui->group_selected == index) && (gui->border_selected)) cairo_set_line_width(cr, 2.0 / zoom_scale); else cairo_set_line_width(cr, 1.0 / zoom_scale); cairo_set_source_rgba(cr, .8, .8, .8, .8); cairo_set_dash(cr, dashed, len, 4); cairo_stroke(cr); } // draw the source if any if(gpt->source_count > 6) { const float radius = fabs(gpt->points[2] - gpt->points[0]); // compute the dest inner circle intersection with the line from source center to dest center. float cdx = gpt->source[0] + dxs - gpt->points[0] - dx; float cdy = gpt->source[1] + dys - gpt->points[1] - dy; // we don't draw the line if source==point if(cdx != 0.0 && cdy != 0.0) { cairo_set_line_cap(cr, CAIRO_LINE_CAP_ROUND); float cangle = atan(cdx / cdy); if(cdy > 0) cangle = (M_PI / 2) - cangle; else cangle = -(M_PI / 2) - cangle; // (arrowx,arrowy) is the point of intersection, we move it (factor 1.11) a bit farther than the // inner circle to avoid superposition. float arrowx = gpt->points[0] + 1.11 * radius * cos(cangle) + dx; float arrowy = gpt->points[1] + 1.11 * radius * sin(cangle) + dy; cairo_move_to(cr, gpt->source[0] + dxs, gpt->source[1] + dys); // source center cairo_line_to(cr, arrowx, arrowy); // dest border // then draw to line for the arrow itself const float arrow_scale = 8.0; cairo_move_to(cr, arrowx + arrow_scale * cos(cangle + (0.4)), arrowy + arrow_scale * sin(cangle + (0.4))); cairo_line_to(cr, arrowx, arrowy); cairo_line_to(cr, arrowx + arrow_scale * cos(cangle - (0.4)), arrowy + arrow_scale * sin(cangle - (0.4))); cairo_set_dash(cr, dashed, 0, 0); if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 2.5 / zoom_scale); else cairo_set_line_width(cr, 1.5 / zoom_scale); cairo_set_source_rgba(cr, .3, .3, .3, .8); cairo_stroke_preserve(cr); if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 1.0 / zoom_scale); else cairo_set_line_width(cr, 0.5 / zoom_scale); cairo_set_source_rgba(cr, .8, .8, .8, .8); cairo_stroke(cr); } // we draw the source cairo_set_dash(cr, dashed, 0, 0); if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 2.5 / zoom_scale); else cairo_set_line_width(cr, 1.5 / zoom_scale); cairo_set_source_rgba(cr, .3, .3, .3, .8); cairo_move_to(cr, gpt->source[2] + dxs, gpt->source[3] + dys); for(int i = 2; i < gpt->source_count; i++) { cairo_line_to(cr, gpt->source[i * 2] + dxs, gpt->source[i * 2 + 1] + dys); } cairo_line_to(cr, gpt->source[2] + dxs, gpt->source[3] + dys); cairo_stroke_preserve(cr); if((gui->group_selected == index) && (gui->form_selected || gui->form_dragging)) cairo_set_line_width(cr, 1.0 / zoom_scale); else cairo_set_line_width(cr, 0.5 / zoom_scale); cairo_set_source_rgba(cr, .8, .8, .8, .8); cairo_stroke(cr); } }
void engine_draw_frame (decor_t * d, cairo_t * cr) { frame_settings *fs = d->fs; private_fs *pfs = fs->engine_fs; window_settings *ws = fs->ws; double x1, y1, x2, y2; x1 = ws->left_space - ws->win_extents.left; y1 = ws->top_space - ws->win_extents.top; x2 = d->width - ws->right_space + ws->win_extents.right; y2 = d->height - ws->bottom_space + ws->win_extents.bottom; int top; top = ws->win_extents.top + ws->titlebar_height; double m1 = MIN(ws->win_extents.left, ws->win_extents.right); double m2 = MIN(ws->win_extents.top, ws->win_extents.bottom); double border_width = MIN(m1, m2); double border_offset = border_width/2.0; cairo_set_line_width (cr, border_width); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); rounded_rectangle (cr, x1 + border_offset, y1 + top - border_offset, x2 - x1 - border_width, y2 - y1 - top, 0, ws, 0); cairo_set_source_alpha_color(cr, &pfs->border); cairo_stroke (cr); /* title bar */ if (pfs->title_bar.alpha != 0.0) { rounded_rectangle (cr, x1, y1, x2 - x1, top, 0, ws, 0); cairo_set_source_alpha_color(cr, &pfs->title_bar); cairo_fill(cr); } else { cairo_save(cr); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_rectangle (cr, 0.0, 0.0, d->width, top + y1 - border_width); cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); cairo_fill(cr); cairo_restore(cr); /* FIXME => find a proper solution for this */ #ifdef SHADOW_FIX cairo_rectangle (cr, 0.0, 0.0, d->width, top + y1 - border_width); cairo_clip(cr); cairo_translate(cr, 0.0, ws->top_space + ws->win_extents.top); draw_shadow_background(d, cr); cairo_translate(cr, 0.0, -ws->top_space - ws->win_extents.top); #endif } }
// This is only used to draw borders. void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) { if (paintingDisabled()) return; StrokeStyle style = strokeStyle(); if (style == NoStroke) return; cairo_t* cr = m_data->cr; cairo_save(cr); float width = strokeThickness(); if (width < 1) width = 1; FloatPoint p1 = point1; FloatPoint p2 = point2; bool isVerticalLine = (p1.x() == p2.x()); adjustLineToPixelBoundaries(p1, p2, width, style); cairo_set_line_width(cr, width); int patWidth = 0; switch (style) { case NoStroke: case SolidStroke: break; case DottedStroke: patWidth = static_cast<int>(width); break; case DashedStroke: patWidth = 3*static_cast<int>(width); break; } setColor(cr, strokeColor()); cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE); if (patWidth) { // Do a rect fill of our endpoints. This ensures we always have the // appearance of being a border. We then draw the actual dotted/dashed line. if (isVerticalLine) { fillRectSourceOver(cr, FloatRect(p1.x() - width/2, p1.y() - width, width, width), strokeColor()); fillRectSourceOver(cr, FloatRect(p2.x() - width/2, p2.y(), width, width), strokeColor()); } else { fillRectSourceOver(cr, FloatRect(p1.x() - width, p1.y() - width/2, width, width), strokeColor()); fillRectSourceOver(cr, FloatRect(p2.x(), p2.y() - width/2, width, width), strokeColor()); } // Example: 80 pixels with a width of 30 pixels. // Remainder is 20. The maximum pixels of line we could paint // will be 50 pixels. int distance = (isVerticalLine ? (point2.y() - point1.y()) : (point2.x() - point1.x())) - 2*static_cast<int>(width); int remainder = distance%patWidth; int coverage = distance-remainder; int numSegments = coverage/patWidth; float patternOffset = 0; // Special case 1px dotted borders for speed. if (patWidth == 1) patternOffset = 1.0; else { bool evenNumberOfSegments = numSegments%2 == 0; if (remainder) evenNumberOfSegments = !evenNumberOfSegments; if (evenNumberOfSegments) { if (remainder) { patternOffset += patWidth - remainder; patternOffset += remainder/2; } else patternOffset = patWidth/2; } else if (!evenNumberOfSegments) { if (remainder) patternOffset = (patWidth - remainder)/2; } } double dash = patWidth; cairo_set_dash(cr, &dash, 1, patternOffset); } cairo_move_to(cr, p1.x(), p1.y()); cairo_line_to(cr, p2.x(), p2.y()); cairo_stroke(cr); cairo_restore(cr); }
static void gtk_css_image_builtin_draw_expander (GtkCssImage *image, cairo_t *cr, double width, double height, gboolean horizontal, gboolean is_rtl, gboolean expanded) { GtkCssImageBuiltin *builtin = GTK_CSS_IMAGE_BUILTIN (image); double vertical_overshoot; int diameter; double radius; double interp; /* interpolation factor for center position */ double x_double_horz, y_double_horz; double x_double_vert, y_double_vert; double x_double, y_double; gdouble angle; gint line_width; gdouble progress; line_width = 1; progress = expanded ? 1 : 0; if (!horizontal) { if (is_rtl) angle = (G_PI) - ((G_PI / 2) * progress); else angle = (G_PI / 2) * progress; } else { if (is_rtl) angle = (G_PI / 2) + ((G_PI / 2) * progress); else angle = (G_PI / 2) - ((G_PI / 2) * progress); } interp = progress; /* Compute distance that the stroke extends beyonds the end * of the triangle we draw. */ vertical_overshoot = line_width / 2.0 * (1. / tan (G_PI / 8)); /* For odd line widths, we end the vertical line of the triangle * at a half pixel, so we round differently. */ if (line_width % 2 == 1) vertical_overshoot = ceil (0.5 + vertical_overshoot) - 0.5; else vertical_overshoot = ceil (vertical_overshoot); /* Adjust the size of the triangle we draw so that the entire stroke fits */ diameter = (gint) MAX (3, width - 2 * vertical_overshoot); /* If the line width is odd, we want the diameter to be even, * and vice versa, so force the sum to be odd. This relationship * makes the point of the triangle look right. */ diameter -= (1 - (diameter + line_width) % 2); radius = diameter / 2.; /* Adjust the center so that the stroke is properly aligned with * the pixel grid. The center adjustment is different for the * horizontal and vertical orientations. For intermediate positions * we interpolate between the two. */ x_double_vert = floor ((width / 2) - (radius + line_width) / 2.) + (radius + line_width) / 2.; y_double_vert = (height / 2) - 0.5; x_double_horz = (width / 2) - 0.5; y_double_horz = floor ((height / 2) - (radius + line_width) / 2.) + (radius + line_width) / 2.; x_double = x_double_vert * (1 - interp) + x_double_horz * interp; y_double = y_double_vert * (1 - interp) + y_double_horz * interp; cairo_translate (cr, x_double, y_double); cairo_rotate (cr, angle); cairo_move_to (cr, - radius / 2., - radius); cairo_line_to (cr, radius / 2., 0); cairo_line_to (cr, - radius / 2., radius); cairo_close_path (cr); cairo_set_line_width (cr, line_width); gdk_cairo_set_source_rgba (cr, &builtin->fg_color); cairo_fill_preserve (cr); gdk_cairo_set_source_rgba (cr, &builtin->border_color); cairo_stroke (cr); }
void dtgtk_cairo_paint_alignment(cairo_t *cr,gint x,gint y,gint w,gint h,gint flags) { gint s=w<h?w:h; cairo_translate(cr, x+(w/2.0)-(s/2.0), y+(h/2.0)-(s/2.0)); cairo_scale(cr,s,s); cairo_set_line_width(cr,0.3); cairo_set_line_cap(cr,CAIRO_LINE_CAP_ROUND); switch (flags>>12) { case 1: // Top left cairo_move_to(cr,0.9,0.1); cairo_line_to(cr,0.1,0.1); cairo_line_to(cr,0.1,0.9); break; case 2: // Top center cairo_move_to(cr,0.1,0.1); cairo_line_to(cr,0.9,0.1); break; case 4: // Top right cairo_move_to(cr,0.1,0.1); cairo_line_to(cr,0.9,0.1); cairo_line_to(cr,0.9,0.9); break; case 8: // left cairo_move_to(cr,0.1,0.1); cairo_line_to(cr,0.1,0.9); break; case 16: // center cairo_move_to(cr,0.1,0.5); cairo_line_to(cr,0.9,0.5); cairo_move_to(cr,0.5,0.1); cairo_line_to(cr,0.5,0.9); break; case 32: // right cairo_move_to(cr,0.9,0.1); cairo_line_to(cr,0.9,0.9); break; case 64: // bottom left cairo_move_to(cr,0.9,0.9); cairo_line_to(cr,0.1,0.9); cairo_line_to(cr,0.1,0.1); break; case 128: // bottom center cairo_move_to(cr,0.1,0.9); cairo_line_to(cr,0.9,0.9); break; case 256: // bottom right cairo_move_to(cr,0.1,0.9); cairo_line_to(cr,0.9,0.9); cairo_line_to(cr,0.9,0.1); break; } cairo_stroke(cr); }