static gboolean dash_box_real_draw (GtkWidget* base, cairo_t* c) { DashBox * self; gboolean result = FALSE; Background* _tmp0_; gdouble box_r; gint box_y; gint box_w = 0; gint box_h = 0; gint _tmp11_ = 0; gint _tmp12_ = 0; DashBoxMode _tmp13_; cairo_t* _tmp25_; cairo_t* _tmp26_; gint _tmp27_; gint _tmp28_; gint _tmp29_; gdouble _tmp30_; cairo_t* _tmp31_; cairo_t* _tmp32_; cairo_t* _tmp33_; cairo_t* _tmp34_; cairo_t* _tmp35_; cairo_t* _tmp36_; cairo_t* _tmp37_; gboolean _tmp38_ = FALSE; self = (DashBox*) base; g_return_val_if_fail (c != NULL, FALSE); _tmp0_ = self->priv->_background; if (_tmp0_ != NULL) { gint x = 0; gint y = 0; Background* _tmp1_; gint _tmp2_ = 0; gint _tmp3_ = 0; cairo_t* _tmp4_; cairo_t* _tmp5_; gint _tmp6_; gint _tmp7_; Background* _tmp8_; cairo_t* _tmp9_; cairo_t* _tmp10_; _tmp1_ = self->priv->_background; gtk_widget_translate_coordinates ((GtkWidget*) _tmp1_, (GtkWidget*) self, 0, 0, &_tmp2_, &_tmp3_); x = _tmp2_; y = _tmp3_; _tmp4_ = c; cairo_save (_tmp4_); _tmp5_ = c; _tmp6_ = x; _tmp7_ = y; cairo_translate (_tmp5_, (gdouble) _tmp6_, (gdouble) _tmp7_); _tmp8_ = self->priv->_background; _tmp9_ = c; background_draw_full (_tmp8_, _tmp9_, BACKGROUND_DRAW_FLAGS_NONE); _tmp10_ = c; cairo_restore (_tmp10_); } box_r = 0.3 * grid_size; box_y = 0; gtk_widget_get_preferred_width ((GtkWidget*) self, NULL, &_tmp11_); box_w = _tmp11_; gtk_widget_get_preferred_height ((GtkWidget*) self, NULL, &_tmp12_); box_h = _tmp12_; _tmp13_ = self->priv->mode; if (_tmp13_ == DASH_BOX_MODE_PUSH_FADE_OUT) { gint _tmp14_; gint _tmp15_; gint _tmp16_; gdouble _tmp17_; gint new_box_h; gint _tmp18_; _tmp14_ = box_h; _tmp15_ = box_h; _tmp16_ = self->priv->orig_height; _tmp17_ = self->priv->_base_alpha; new_box_h = _tmp14_ - ((gint) ((_tmp15_ - _tmp16_) * _tmp17_)); _tmp18_ = new_box_h; box_h = _tmp18_; } else { DashBoxMode _tmp19_; _tmp19_ = self->priv->mode; if (_tmp19_ == DASH_BOX_MODE_POP_FADE_IN) { gint _tmp20_; gint _tmp21_; gint _tmp22_; gdouble _tmp23_; gint new_box_h; gint _tmp24_; _tmp20_ = box_h; _tmp21_ = box_h; _tmp22_ = self->priv->orig_height; _tmp23_ = self->priv->_base_alpha; new_box_h = _tmp20_ - ((gint) ((_tmp21_ - _tmp22_) * _tmp23_)); _tmp24_ = new_box_h; box_h = _tmp24_; } } _tmp25_ = c; cairo_save (_tmp25_); _tmp26_ = c; _tmp27_ = box_y; _tmp28_ = box_w; _tmp29_ = box_h; _tmp30_ = box_r; dash_box_cairo_rounded_rectangle (_tmp26_, (gdouble) 0, (gdouble) _tmp27_, (gdouble) _tmp28_, (gdouble) _tmp29_, _tmp30_); _tmp31_ = c; cairo_set_source_rgba (_tmp31_, 0.1, 0.1, 0.1, 0.4); _tmp32_ = c; cairo_fill_preserve (_tmp32_); _tmp33_ = c; cairo_set_source_rgba (_tmp33_, 0.4, 0.4, 0.4, 0.4); _tmp34_ = c; cairo_set_line_width (_tmp34_, (gdouble) 1); _tmp35_ = c; cairo_stroke (_tmp35_); _tmp36_ = c; cairo_restore (_tmp36_); _tmp37_ = c; _tmp38_ = GTK_WIDGET_CLASS (dash_box_parent_class)->draw ((GtkWidget*) G_TYPE_CHECK_INSTANCE_CAST (self, GTK_TYPE_BOX, GtkBox), _tmp37_); result = _tmp38_; return result; }
static void draw_line(struct clickdot *clickdot, cairo_t *cr, struct rectangle *allocation) { cairo_t *bcr; cairo_surface_t *tmp_buffer = NULL; if (clickdot->reset) { tmp_buffer = clickdot->buffer; clickdot->buffer = NULL; clickdot->line.x = -1; clickdot->line.y = -1; clickdot->line.old_x = -1; clickdot->line.old_y = -1; clickdot->reset = 0; } if (clickdot->buffer == NULL) { clickdot->buffer = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, allocation->width, allocation->height); bcr = cairo_create(clickdot->buffer); cairo_set_source_rgba(bcr, 0, 0, 0, 0); cairo_rectangle(bcr, 0, 0, allocation->width, allocation->height); cairo_fill(bcr); } else bcr = cairo_create(clickdot->buffer); if (tmp_buffer) { cairo_set_source_surface(bcr, tmp_buffer, 0, 0); cairo_rectangle(bcr, 0, 0, allocation->width, allocation->height); cairo_clip(bcr); cairo_paint(bcr); cairo_surface_destroy(tmp_buffer); } if (clickdot->line.x != -1 && clickdot->line.y != -1) { if (clickdot->line.old_x != -1 && clickdot->line.old_y != -1) { cairo_set_line_width(bcr, 2.0); cairo_set_source_rgb(bcr, 1, 1, 1); cairo_translate(bcr, -allocation->x, -allocation->y); cairo_move_to(bcr, clickdot->line.old_x, clickdot->line.old_y); cairo_line_to(bcr, clickdot->line.x, clickdot->line.y); cairo_stroke(bcr); } clickdot->line.old_x = clickdot->line.x; clickdot->line.old_y = clickdot->line.y; } cairo_destroy(bcr); cairo_set_source_surface(cr, clickdot->buffer, allocation->x, allocation->y); cairo_set_operator(cr, CAIRO_OPERATOR_ADD); cairo_rectangle(cr, allocation->x, allocation->y, allocation->width, allocation->height); cairo_clip(cr); cairo_paint(cr); }
static void expose_filemanager (dt_view_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { dt_library_t *lib = (dt_library_t *)self->data; gboolean offset_changed = FALSE; /* query new collection count */ lib->collection_count = dt_collection_get_count (darktable.collection); if(darktable.gui->center_tooltip == 1) darktable.gui->center_tooltip = 2; /* get grid stride */ const int iir = dt_conf_get_int("plugins/lighttable/images_in_row"); /* get image over id */ lib->image_over = DT_VIEW_DESERT; int32_t mouse_over_id, mouse_over_group = -1; DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); /* fill background */ cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); if(lib->first_visible_zoomable >= 0) { lib->offset = lib->first_visible_zoomable; } lib->first_visible_zoomable = -1; /* check if offset has been changed */ if(lib->track > 2) lib->offset += iir; if(lib->track < -2) lib->offset -= iir; lib->track = 0; if(lib->center) lib->offset = 0; lib->center = 0; int offset = lib->offset; /* if offset differs then flag as changed */ if (offset != lib->first_visible_filemanager) offset_changed = TRUE; lib->first_visible_filemanager = offset; static int oldpan = 0; const int pan = lib->pan; const float wd = width/(float)iir; const float ht = width/(float)iir; int pi = pointerx / (float)wd; int pj = pointery / (float)ht; if(pointerx < 0 || pointery < 0) pi = pj = -1; //const int pidx = grid_to_index(pj, pi, iir, offset); const int img_pointerx = iir == 1 ? pointerx : fmodf(pointerx, wd); const int img_pointery = iir == 1 ? pointery : fmodf(pointery, ht); const int max_rows = 1 + (int)((height)/ht + .5); const int max_cols = iir; int id; int clicked1 = (oldpan == 0 && pan == 1 && lib->button == 1); /* get the count of current collection */ if(lib->collection_count == 0) { const float fs = 15.0f; const float ls = 1.5f*fs; const float offy = height*0.2f; const float offx = 60; const float at = 0.3f; cairo_set_font_size(cr, fs); cairo_set_source_rgba(cr, .7, .7, .7, 1.0f); cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL); cairo_move_to(cr, offx, offy); cairo_show_text(cr, _("there are no images in this collection")); cairo_move_to(cr, offx, offy + 2*ls); cairo_show_text(cr, _("if you have not imported any images yet")); cairo_move_to(cr, offx, offy + 3*ls); cairo_show_text(cr, _("you can do so in the import module")); cairo_move_to(cr, offx - 10.0f, offy + 3*ls - ls*.25f); cairo_line_to(cr, 0.0f, 10.0f); cairo_set_source_rgba(cr, .7, .7, .7, at); cairo_stroke(cr); cairo_move_to(cr, offx, offy + 5*ls); cairo_set_source_rgba(cr, .7, .7, .7, 1.0f); cairo_show_text(cr, _("try to relax the filter settings in the top panel")); cairo_rel_move_to(cr, 10.0f, -ls*.25f); cairo_line_to(cr, width*0.5f, 0.0f); cairo_set_source_rgba(cr, .7, .7, .7, at); cairo_stroke(cr); cairo_move_to(cr, offx, offy + 6*ls); cairo_set_source_rgba(cr, .7, .7, .7, 1.0f); cairo_show_text(cr, _("or add images in the collection module in the left panel")); cairo_move_to(cr, offx - 10.0f, offy + 6*ls - ls*0.25f); cairo_rel_line_to(cr, - offx + 10.0f, 0.0f); cairo_set_source_rgba(cr, .7, .7, .7, at); cairo_stroke(cr); return; } /* do we have a main query collection statement */ if(!lib->statements.main_query) return; if(offset < 0) lib->offset = offset = 0; while(offset >= lib->collection_count) lib->offset = (offset -= iir); /* update scroll borders */ dt_view_set_scrollbar(self, 0, 1, 1, offset, lib->collection_count, max_rows*iir); /* let's reset and reuse the main_query statement */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); /* setup offset and row for the main query */ DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 1, offset); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 2, max_rows*iir); if(mouse_over_id != -1) { const dt_image_t *mouse_over_image = dt_image_cache_read_get(darktable.image_cache, mouse_over_id); mouse_over_group = mouse_over_image->group_id; dt_image_cache_read_release(darktable.image_cache, mouse_over_image); DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.is_grouped); DT_DEBUG_SQLITE3_RESET(lib->statements.is_grouped); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.is_grouped, 1, mouse_over_group); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.is_grouped, 2, mouse_over_id); if(sqlite3_step(lib->statements.is_grouped) != SQLITE_ROW) mouse_over_group = -1; } // prefetch the ids so that we can peek into the future to see if there are adjacent images in the same group. int *query_ids = g_malloc0(max_rows*max_cols*sizeof(int)); for(int row = 0; row < max_rows; row++) { for(int col = 0; col < max_cols; col++) { if(sqlite3_step(lib->statements.main_query) == SQLITE_ROW) query_ids[row*iir+col] = sqlite3_column_int(lib->statements.main_query, 0); else goto end_query_cache; } } end_query_cache: cairo_save(cr); for(int row = 0; row < max_rows; row++) { for(int col = 0; col < max_cols; col++) { //curidx = grid_to_index(row, col, iir, offset); id = query_ids[row*iir+col]; if(id > 0) { if (iir == 1 && row) continue; /* set mouse over id if pointer is in current row / col */ if(pi == col && pj == row) { mouse_over_id = id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, mouse_over_id); } /* handle mouse click on current row / col this could easily and preferable be moved to button_pressed() */ if (clicked1 && (pi == col && pj == row)) { if ((lib->modifiers & (GDK_SHIFT_MASK|GDK_CONTROL_MASK)) == 0) dt_selection_select_single(darktable.selection, id); else if ((lib->modifiers & (GDK_CONTROL_MASK)) == GDK_CONTROL_MASK) dt_selection_toggle(darktable.selection, id); else if ((lib->modifiers & (GDK_SHIFT_MASK)) == GDK_SHIFT_MASK) dt_selection_select_range(darktable.selection, id); } cairo_save(cr); // if(iir == 1) dt_image_prefetch(image, DT_IMAGE_MIPF); dt_view_image_expose(&(lib->image_over), id, cr, wd, iir == 1 ? height : ht, iir, img_pointerx, img_pointery); cairo_restore(cr); } else goto failure; cairo_translate(cr, wd, 0.0f); } cairo_translate(cr, -max_cols*wd, ht); } cairo_restore(cr); // and now the group borders for(int row = 0; row < max_rows; row++) { for(int col = 0; col < max_cols; col++) { id = query_ids[row*iir+col]; if(id > 0) { const dt_image_t *image = dt_image_cache_read_get(darktable.image_cache, id); int group_id = -1; if(image) group_id = image->group_id; dt_image_cache_read_release(darktable.image_cache, image); if (iir == 1 && row) continue; cairo_save(cr); gboolean paint_border = FALSE; // regular highlight border if(group_id != -1) { if(mouse_over_group == group_id && iir > 1 && ((!darktable.gui->grouping && dt_conf_get_bool("plugins/lighttable/draw_group_borders")) || group_id == darktable.gui->expanded_group_id)) { cairo_set_source_rgb(cr, 1, 0.8, 0); paint_border = TRUE; } // border of expanded group else if(darktable.gui->grouping && group_id == darktable.gui->expanded_group_id && iir > 1) { cairo_set_source_rgb(cr, 0, 0, 1); paint_border = TRUE; } } if(paint_border) { int neighbour_group = -1; // top border if(row > 0) { int _id = query_ids[(row-1)*iir+col]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, 0, 0); cairo_line_to(cr, wd, 0); } // left border neighbour_group = -1; if(col > 0) { int _id = query_ids[row*iir+(col-1)]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, 0, 0); cairo_line_to(cr, 0, ht); } // bottom border neighbour_group = -1; if(row < max_rows-1) { int _id = query_ids[(row+1)*iir+col]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, 0, ht); cairo_line_to(cr, wd, ht); } // right border neighbour_group = -1; if(col < max_cols-1) { int _id = query_ids[row*iir+(col+1)]; if(_id > 0) { const dt_image_t *_img = dt_image_cache_read_get(darktable.image_cache, _id); neighbour_group = _img->group_id; dt_image_cache_read_release(darktable.image_cache, _img); } } if(neighbour_group != group_id) { cairo_move_to(cr, wd, 0); cairo_line_to(cr, wd, ht); } cairo_set_line_width(cr, 0.01*wd); cairo_stroke(cr); } cairo_restore(cr); } else goto failure; cairo_translate(cr, wd, 0.0f); } cairo_translate(cr, -max_cols*wd, ht); } /* check if offset was changed and we need to prefetch thumbs */ if (offset_changed) { int32_t imgids_num = 0; const int prefetchrows = .5*max_rows+1; int32_t imgids[prefetchrows*iir]; /* clear and reset main query */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); /* setup offest and row for prefetch */ DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 1, offset + max_rows*iir); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 2, prefetchrows*iir); // prefetch jobs in inverse order: supersede previous jobs: most important last while(sqlite3_step(lib->statements.main_query) == SQLITE_ROW && imgids_num < prefetchrows*iir) imgids[imgids_num++] = sqlite3_column_int(lib->statements.main_query, 0); float imgwd = iir == 1 ? 0.97 : 0.8; dt_mipmap_size_t mip = dt_mipmap_cache_get_matching_size( darktable.mipmap_cache, imgwd*wd, imgwd*(iir==1?height:ht)); while(imgids_num > 0) { imgids_num --; dt_mipmap_buffer_t buf; dt_mipmap_cache_read_get( darktable.mipmap_cache, &buf, imgids[imgids_num], mip, DT_MIPMAP_PREFETCH); } } failure: g_free(query_ids); oldpan = pan; if(darktable.unmuted & DT_DEBUG_CACHE) dt_mipmap_cache_print(darktable.mipmap_cache); if(darktable.gui->center_tooltip == 1) // set in this round { char* tooltip = dt_history_get_items_as_string(mouse_over_id); if(tooltip != NULL) { g_object_set(G_OBJECT(dt_ui_center(darktable.gui->ui)), "tooltip-text", tooltip, (char *)NULL); g_free(tooltip); } } else if(darktable.gui->center_tooltip == 2) // not set in this round { darktable.gui->center_tooltip = 0; g_object_set(G_OBJECT(dt_ui_center(darktable.gui->ui)), "tooltip-text", "", (char *)NULL); } }
int main(int argc, char **argv){ float width=8.5*72.0; float height=11.0*72.0; float xoff=0; float yoff=0; float fontsize=-1; int havey=0; float dpp=300.0/72.0; char *text=NULL; int c,long_option_index; cairo_surface_t *cs; cairo_t *ct; cairo_text_extents_t extents; while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){ switch(c){ case 'W': case 'H': case 'x': case 'y': { float temp; if(strstr(optarg,"cm")){ temp=atof(optarg)*28.3464566929; }else if (strstr(optarg,"mm")){ temp=atof(optarg)*2.83464566929; }else if (strstr(optarg,"pt")){ temp=atof(optarg); }else{ temp=atof(optarg)*72.0; } switch(c){ case 'W': width=temp; break; case 'H': height=temp; break; case 'x': xoff=temp; break; case 'y': yoff=temp; havey=1; break; } } break; case 'r': if(strstr(optarg,"dpcm")){ dpp=atof(optarg)*.03527777777778; }else if (strstr(optarg,"dpmm")){ dpp=atof(optarg)*.35277777777778; }else if (strstr(optarg,"dpp")){ dpp=atof(optarg); }else{ dpp=atof(optarg)*.01388888888889; } break; case 'f': fontsize=atof(optarg); break; case 't': text=strdup(optarg); break; case 'h': usage(stdout); exit(0); case 'v': fprintf(stderr,"pngxpdf "VERSION"\n"); default: usage(stderr); } } /* set up our surface */ cs = cairo_pdf_surface_create_for_stream (pdf_write, NULL, width, height); if(!cs || cairo_surface_status(cs)!=CAIRO_STATUS_SUCCESS){ fprintf(stderr,"CAIRO ERROR: Unable to create PDF surface.\n\n"); exit(1); } ct = cairo_create(cs); if(fontsize<=0){ fontsize=height*15./792.; if(fontsize<5)fontsize=5; } cairo_set_font_size(ct, fontsize); if(text){ cairo_text_extents(ct, text, &extents); if(!havey) yoff = -extents.height-fontsize*4; } /* Iterate through PNG files inline */ while(optind<argc){ int ww, hh; char *filename = argv[optind]; cairo_pattern_t *pattern; cairo_surface_t *ps=cairo_image_surface_create_from_png(filename); cairo_status_t status = cairo_surface_status(ps); if(!ps || status!=CAIRO_STATUS_SUCCESS){ fprintf(stderr,"CAIRO ERROR: Unable to load PNG file %s: %s\n\n",filename,cairo_status_to_string(status)); exit(1); } ww = cairo_image_surface_get_width(ps); hh = cairo_image_surface_get_height(ps); cairo_save(ct); cairo_scale(ct, 1./dpp, 1./dpp); pattern = cairo_pattern_create_for_surface(ps); cairo_translate(ct,(width*dpp - (ww-1))*.5,((height+yoff)*dpp - (hh-1))*.5); cairo_pattern_set_filter(pattern, CAIRO_FILTER_BEST); cairo_set_source(ct,pattern); cairo_paint(ct); cairo_restore(ct); /* draw comment text */ if(text){ cairo_set_source_rgba(ct, 1,1,1,.75); cairo_move_to(ct, width-extents.width-fontsize*1.5, height-fontsize*1.5); cairo_text_path (ct, text); cairo_set_line_width(ct,3.); cairo_set_line_join(ct,CAIRO_LINE_JOIN_ROUND); cairo_stroke(ct); cairo_set_source_rgb(ct, 0,0,0); cairo_move_to(ct, width-extents.width-fontsize*1.5, height-fontsize*1.5); cairo_show_text(ct, text); } cairo_surface_show_page(cs); cairo_surface_destroy(ps); optind++; } cairo_destroy(ct); cairo_surface_destroy(cs); }
static void draw_page_cairo(GtkPrintContext *context, PrintData *data) { cairo_t *cr; GdkPixbuf *pixbuf_to_draw; cairo_surface_t *surface; guchar *surface_pixels; guchar *pixbuf_pixels; gint stride; gint pixbuf_stride; gint pixbuf_n_channels; gdouble cr_dpi_x; gdouble cr_dpi_y; gdouble scale_x; gdouble scale_y; gint y; cr = gtk_print_context_get_cairo_context(context); pixbuf_to_draw = gdk_pixbuf_get_from_drawable(NULL, GDK_DRAWABLE(vik_viewport_get_pixmap(data->vvp)), NULL, 0, 0, 0, 0, data->width, data->height); surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, data->width, data->height); cr_dpi_x = gtk_print_context_get_dpi_x (context); cr_dpi_y = gtk_print_context_get_dpi_y (context); scale_x = cr_dpi_x / data->xres; scale_y = cr_dpi_y / data->yres; cairo_translate (cr, data->offset_x / cr_dpi_x * 72.0, data->offset_y / cr_dpi_y * 72.0); cairo_scale (cr, scale_x, scale_y); surface_pixels = cairo_image_surface_get_data (surface); stride = cairo_image_surface_get_stride (surface); pixbuf_pixels = gdk_pixbuf_get_pixels (pixbuf_to_draw); pixbuf_stride = gdk_pixbuf_get_rowstride(pixbuf_to_draw); pixbuf_n_channels = gdk_pixbuf_get_n_channels(pixbuf_to_draw); // fprintf(stderr, "DEBUG: %s() surface_pixels=%p pixbuf_pixels=%p size=%d surface_width=%d surface_height=%d stride=%d data_height=%d pixmap_stride=%d pixmap_nchannels=%d pixmap_bit_per_Sample=%d\n", __PRETTY_FUNCTION__, surface_pixels, pixbuf_pixels, stride * data->height, cairo_image_surface_get_width(surface), cairo_image_surface_get_height(surface), stride, data->height, gdk_pixbuf_get_rowstride(pixbuf_to_draw), gdk_pixbuf_get_n_channels(pixbuf_to_draw), gdk_pixbuf_get_bits_per_sample(pixbuf_to_draw)); /* Assume the pixbuf has 8 bits per channel */ for (y = 0; y < data->height; y++, surface_pixels += stride, pixbuf_pixels += pixbuf_stride) { switch (pixbuf_n_channels) { case 3: copy_row_from_rgb (surface_pixels, pixbuf_pixels, data->width); break; case 4: copy_row_from_rgba (surface_pixels, pixbuf_pixels, data->width); break; } } g_object_unref(G_OBJECT(pixbuf_to_draw)); cairo_set_source_surface(cr, surface, 0, 0); cairo_rectangle(cr, 0, 0, data->width, data->height); cairo_fill(cr); cairo_surface_destroy(surface); }
static void _cairo_render_text (CairoRenderer *renderer, PinPointPoint *point) { PangoLayout *layout; PangoFontDescription *desc; PangoRectangle logical_rect = { 0, }; ClutterColor text_color, shading_color; float text_x, text_y, text_width, text_height, text_scale; float shading_x, shading_y, shading_width, shading_height; if (point == NULL) return; layout = pango_cairo_create_layout (renderer->ctx); desc = pango_font_description_from_string (point->font); pango_layout_set_font_description (layout, desc); if (point->use_markup) pango_layout_set_markup (layout, point->text, -1); else pango_layout_set_text (layout, point->text, -1); pango_layout_set_alignment (layout, point->text_align); pango_layout_get_extents (layout, NULL, &logical_rect); text_width = (logical_rect.x + logical_rect.width) / 1024; text_height = (logical_rect.y + logical_rect.height) / 1024; if (text_width < 1) goto out; pp_get_text_position_scale (point, renderer->width, renderer->height, text_width, text_height, &text_x, &text_y, &text_scale); pp_get_shading_position_size (renderer->height, renderer->width, /* XXX: is this right order?? */ text_x, text_y, text_width, text_height, text_scale, &shading_x, &shading_y, &shading_width, &shading_height); clutter_color_from_string (&text_color, point->text_color); clutter_color_from_string (&shading_color, point->shading_color); cairo_set_source_rgba (renderer->ctx, shading_color.red / 255.f, shading_color.green / 255.f, shading_color.blue / 255.f, shading_color.alpha / 255.f * point->shading_opacity); cairo_rectangle (renderer->ctx, shading_x, shading_y, shading_width, shading_height); cairo_fill (renderer->ctx); cairo_save (renderer->ctx); cairo_translate (renderer->ctx, text_x, text_y); cairo_scale (renderer->ctx, text_scale, text_scale); cairo_set_source_rgba (renderer->ctx, text_color.red / 255.f, text_color.green / 255.f, text_color.blue / 255.f, text_color.alpha / 255.f); pango_cairo_show_layout (renderer->ctx, layout); cairo_restore (renderer->ctx); out: pango_font_description_free (desc); g_object_unref (layout); }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { cairo_pattern_t *gradient, *image; cairo_set_source_rgb (cr, 1,1,1); cairo_paint (cr); cairo_translate (cr, PAD, PAD); /* clip to the unit size */ cairo_rectangle (cr, 0, 0, UNIT_SIZE, UNIT_SIZE); cairo_clip (cr); cairo_rectangle (cr, 0, 0, UNIT_SIZE, UNIT_SIZE); cairo_set_source_rgba (cr, 0, 0, 0, 1); cairo_set_line_width (cr, 2); cairo_stroke (cr); /* start a group */ cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR); /* draw a gradient background */ cairo_save (cr); cairo_translate (cr, INNER_PAD, INNER_PAD); cairo_new_path (cr); cairo_rectangle (cr, 0, 0, UNIT_SIZE - (INNER_PAD*2), UNIT_SIZE - (INNER_PAD*2)); gradient = cairo_pattern_create_linear (UNIT_SIZE - (INNER_PAD*2), 0, UNIT_SIZE - (INNER_PAD*2), UNIT_SIZE - (INNER_PAD*2)); cairo_pattern_add_color_stop_rgba (gradient, 0.0, 0.3, 0.3, 0.3, 1.0); cairo_pattern_add_color_stop_rgba (gradient, 1.0, 1.0, 1.0, 1.0, 1.0); cairo_set_source (cr, gradient); cairo_pattern_destroy (gradient); cairo_fill (cr); cairo_restore (cr); /* draw diamond */ cairo_move_to (cr, UNIT_SIZE / 2, 0); cairo_line_to (cr, UNIT_SIZE , UNIT_SIZE / 2); cairo_line_to (cr, UNIT_SIZE / 2, UNIT_SIZE); cairo_line_to (cr, 0 , UNIT_SIZE / 2); cairo_close_path (cr); cairo_set_source_rgba (cr, 0, 0, 1, 1); cairo_fill (cr); /* draw circle */ cairo_arc (cr, UNIT_SIZE / 2, UNIT_SIZE / 2, UNIT_SIZE / 3.5, 0, M_PI * 2); cairo_set_source_rgba (cr, 1, 0, 0, 1); cairo_fill (cr); /* and put the image on top */ cairo_translate (cr, UNIT_SIZE/2 - 8, UNIT_SIZE/2 - 8); image = argb32_source (); cairo_set_source (cr, image); cairo_pattern_destroy (image); cairo_paint (cr); cairo_pop_group_to_source (cr); cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); cairo_paint (cr); return CAIRO_TEST_SUCCESS; }
static gboolean gimp_color_bar_expose (GtkWidget *widget, GdkEventExpose *event) { GimpColorBar *bar = GIMP_COLOR_BAR (widget); cairo_t *cr; GtkAllocation allocation; cairo_surface_t *surface; cairo_pattern_t *pattern; guchar *src; guchar *dest; gint x, y; gint width, height; gint i; cr = gdk_cairo_create (event->window); gdk_cairo_region (cr, event->region); cairo_clip (cr); gtk_widget_get_allocation (widget, &allocation); x = y = gtk_container_get_border_width (GTK_CONTAINER (bar)); width = allocation.width - 2 * x; height = allocation.height - 2 * y; if (width < 1 || height < 1) return TRUE; cairo_translate (cr, allocation.x + x, allocation.y + y); cairo_rectangle (cr, 0, 0, width, height); cairo_clip (cr); surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 256, 1); for (i = 0, src = bar->buf, dest = cairo_image_surface_get_data (surface); i < 256; i++, src += 3, dest += 4) { GIMP_CAIRO_RGB24_SET_PIXEL(dest, src[0], src[1], src[2]); } cairo_surface_mark_dirty (surface); pattern = cairo_pattern_create_for_surface (surface); cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REFLECT); cairo_surface_destroy (surface); if (bar->orientation == GTK_ORIENTATION_HORIZONTAL) { cairo_scale (cr, (gdouble) width / 256.0, 1.0); } else { cairo_translate (cr, 0, height); cairo_scale (cr, 1.0, (gdouble) height / 256.0); cairo_rotate (cr, - G_PI / 2); } cairo_set_source (cr, pattern); cairo_pattern_destroy (pattern); cairo_paint (cr); cairo_destroy (cr); return TRUE; }
static gboolean dt_iop_zonesystem_bar_expose (GtkWidget *widget, GdkEventExpose *event, 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 = 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, 1.); const float arrw = 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_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 content_draw_cb (GtkWidget *widget, cairo_t *cr, gpointer user_data) { PangoContext *context; PangoLayout *title_layout; PangoLayout *sub_layout; PangoFontDescription *desc; int width, height; cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); cairo_paint (cr); width = gdk_window_get_width (gtk_widget_get_window (widget)); height = gdk_window_get_height (gtk_widget_get_window (widget)); cairo_translate (cr, width / 2, height / 2); context = gdk_pango_context_get_for_screen (gtk_widget_get_screen (widget)); title_layout = pango_layout_new (context); pango_layout_set_text (title_layout, _("This session is locked."), -1); desc = pango_font_description_from_string (TITLE_FONT); pango_layout_set_font_description (title_layout, desc); pango_font_description_free (desc); cairo_set_source_rgba (cr, 1.0, 1.0, 1.0, 1.0); pango_cairo_update_layout (cr, title_layout); pango_layout_get_size (title_layout, &width, &height); cairo_save (cr); /* Adjust the translation to the middle left of the icon */ cairo_translate (cr, - width / PANGO_SCALE / 2 - height / PANGO_SCALE, - height / PANGO_SCALE / 2); draw_lock_icon (cr, height / PANGO_SCALE); cairo_restore (cr); cairo_move_to (cr, - width / PANGO_SCALE / 2 + height / PANGO_SCALE, - height / PANGO_SCALE); pango_cairo_show_layout (cr, title_layout); g_object_unref (title_layout); sub_layout = pango_layout_new (context); pango_layout_set_text (sub_layout, _("You'll be redirected to the unlock dialog automatically in a few seconds."), -1); pango_layout_set_wrap (sub_layout, PANGO_WRAP_WORD_CHAR); pango_layout_set_width (sub_layout, width + 2 * height); desc = pango_font_description_from_string (MESSAGE_FONT); pango_layout_set_font_description (sub_layout, desc); pango_font_description_free (desc); cairo_set_source_rgba (cr, 0.6, 0.6, 0.6, 1.0); pango_cairo_update_layout (cr, sub_layout); pango_layout_get_size (sub_layout, &width, NULL); cairo_move_to (cr, - width / PANGO_SCALE / 2, height / PANGO_SCALE); pango_cairo_show_layout (cr, sub_layout); g_object_unref (sub_layout); g_object_unref (context); }
static gboolean dt_iop_tonecurve_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { dt_iop_module_t *self = (dt_iop_module_t *)user_data; dt_iop_tonecurve_gui_data_t *c = (dt_iop_tonecurve_gui_data_t *)self->gui_data; dt_iop_tonecurve_params_t *p = (dt_iop_tonecurve_params_t *)self->params; const float color_labels_left[3][3] = { { 0.3f, 0.3f, 0.3f }, { 0.0f, 0.34f, 0.27f }, { 0.0f, 0.27f, 0.58f } }; const float color_labels_right[3][3] = {{ 0.3f, 0.3f, 0.3f }, { 0.53f, 0.08f, 0.28f}, { 0.81f, 0.66f, 0.0f } }; int ch = c->channel; int nodes = p->tonecurve_nodes[ch]; dt_iop_tonecurve_node_t *tonecurve = p->tonecurve[ch]; int autoscale_ab = p->tonecurve_autoscale_ab; if(c->minmax_curve_type[ch] != p->tonecurve_type[ch] || c->minmax_curve_nodes[ch] != p->tonecurve_nodes[ch]) { dt_draw_curve_destroy(c->minmax_curve[ch]); c->minmax_curve[ch] = dt_draw_curve_new(0.0, 1.0, p->tonecurve_type[ch]); c->minmax_curve_nodes[ch] = p->tonecurve_nodes[ch]; c->minmax_curve_type[ch] = p->tonecurve_type[ch]; for(int k=0; k<p->tonecurve_nodes[ch]; k++) (void)dt_draw_curve_add_point(c->minmax_curve[ch], p->tonecurve[ch][k].x, p->tonecurve[ch][k].y); } else { for(int k=0; k<p->tonecurve_nodes[ch]; k++) dt_draw_curve_set_point(c->minmax_curve[ch], k, p->tonecurve[ch][k].x, p->tonecurve[ch][k].y); } dt_draw_curve_t *minmax_curve = c->minmax_curve[ch]; dt_draw_curve_calc_values(minmax_curve, 0.0, 1.0, DT_IOP_TONECURVE_RES, c->draw_xs, c->draw_ys); const float xm = tonecurve[nodes-1].x; const float x[4] = {0.7f*xm, 0.8f*xm, 0.9f*xm, 1.0f*xm}; const float y[4] = {c->draw_ys[CLAMP((int)(x[0]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)], c->draw_ys[CLAMP((int)(x[1]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)], c->draw_ys[CLAMP((int)(x[2]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)], c->draw_ys[CLAMP((int)(x[3]*DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES-1)] }; float unbounded_coeffs[3]; dt_iop_estimate_exp(x, y, 4, unbounded_coeffs); 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; #if 0 // draw shadow around float alpha = 1.0f; for(int k=0; k<inset; k++) { cairo_rectangle(cr, -k, -k, width + 2*k, height + 2*k); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.6f; cairo_fill(cr); } #else 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); #endif cairo_set_source_rgb (cr, .3, .3, .3); cairo_rectangle(cr, 0, 0, width, height); cairo_fill(cr); // draw color labels const int cells = 8; for(int j=0; j<cells; j++) { for(int i=0; i<cells; i++) { const float f = (cells-1-j+i)/(2.0f*cells-2.0f); cairo_set_source_rgba (cr, (1.0f-f)*color_labels_left[ch][0] + f*color_labels_right[ch][0], (1.0f-f)*color_labels_left[ch][1] + f*color_labels_right[ch][1], (1.0f-f)*color_labels_left[ch][2] + f*color_labels_right[ch][2], .5f); // blend over to make colors darker, so the overlay is more visible cairo_rectangle(cr, width*i/(float)cells, height*j/(float)cells, width/(float)cells, height/(float)cells); cairo_fill(cr); } } // draw grid cairo_set_line_width(cr, .4); cairo_set_source_rgb (cr, .1, .1, .1); dt_draw_grid(cr, 4, 0, 0, width, height); // if autoscale_ab is on: do not display a and b curves if (autoscale_ab && ch != ch_L) goto finally; // draw nodes positions cairo_set_line_width(cr, 1.); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_translate(cr, 0, height); for(int k=0; k<nodes; k++) { cairo_arc(cr, tonecurve[k].x*width, -tonecurve[k].y*height, 3, 0, 2.*M_PI); cairo_stroke(cr); } // draw selected cursor cairo_set_line_width(cr, 1.); // draw lum h istogram in background // only if module is enabled if (self->enabled) { dt_develop_t *dev = darktable.develop; float *hist, hist_max; float *raw_mean, *raw_min, *raw_max; float *raw_mean_output; float picker_mean[3], picker_min[3], picker_max[3]; char text[256]; raw_mean = self->picked_color; raw_min = self->picked_color_min; raw_max = self->picked_color_max; raw_mean_output = self->picked_output_color; hist = dev->histogram_pre_tonecurve; hist_max = dev->histogram_linear?dev->histogram_pre_tonecurve_max:logf(1.0 + dev->histogram_pre_tonecurve_max); if(hist_max > 0 && ch == ch_L) { 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); } if(self->request_color_pick) { // the global live samples ... GSList *samples = darktable.lib->proxy.colorpicker.live_samples; dt_colorpicker_sample_t *sample = NULL; while(samples) { sample = samples->data; picker_scale(sample->picked_color_lab_mean, picker_mean); picker_scale(sample->picked_color_lab_min, picker_min); picker_scale(sample->picked_color_lab_max, picker_max); cairo_set_source_rgba(cr, 0.5, 0.7, 0.5, 0.15); cairo_rectangle(cr, width*picker_min[ch], 0, width*fmax(picker_max[ch]-picker_min[ch], 0.0f), -height); cairo_fill(cr); cairo_set_source_rgba(cr, 0.5, 0.7, 0.5, 0.5); cairo_move_to(cr, width*picker_mean[ch], 0); cairo_line_to(cr, width*picker_mean[ch], -height); cairo_stroke(cr); samples = g_slist_next(samples); } // ... and the local sample picker_scale(raw_mean, picker_mean); picker_scale(raw_min, picker_min); picker_scale(raw_max, picker_max); cairo_set_source_rgba(cr, 0.7, 0.5, 0.5, 0.33); cairo_rectangle(cr, width*picker_min[ch], 0, width*fmax(picker_max[ch]-picker_min[ch], 0.0f), -height); cairo_fill(cr); cairo_set_source_rgba(cr, 0.9, 0.7, 0.7, 0.5); cairo_move_to(cr, width*picker_mean[ch], 0); cairo_line_to(cr, width*picker_mean[ch], -height); cairo_stroke(cr); snprintf(text, 256, "%.1f → %.1f", raw_mean[ch], raw_mean_output[ch]); cairo_set_source_rgb(cr, 0.1, 0.1, 0.1); cairo_select_font_face (cr, "sans-serif", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_BOLD); cairo_set_font_size (cr, 0.06*height); cairo_move_to (cr, 0.02f*width, -0.94*height); cairo_show_text(cr, text); cairo_stroke(cr); } } if(c->selected >= 0) { cairo_set_source_rgb(cr, .9, .9, .9); cairo_arc(cr, tonecurve[c->selected].x*width, -tonecurve[c->selected].y*height, 4, 0, 2.*M_PI); cairo_stroke(cr); } // draw curve cairo_set_line_width(cr, 2.); cairo_set_source_rgb(cr, .9, .9, .9); // cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_move_to(cr, 0, -height*c->draw_ys[0]); for(int k=1; k<DT_IOP_TONECURVE_RES; k++) { const float xx = k/(DT_IOP_TONECURVE_RES-1.0); if(xx > xm) { const float yy = dt_iop_eval_exp(unbounded_coeffs, xx); cairo_line_to(cr, xx*width, - height*yy); } else { cairo_line_to(cr, xx*width, - height*c->draw_ys[k]); } } cairo_stroke(cr); finally: 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; }
//! //! @brief To be written //! static void _kanjipadwindow_draw_candidate_character (GwKanjipadWindow *window, int index, int selected) { //Declarations GwKanjipadWindowPrivate *priv; PangoLayout *layout; gchar *string_utf; gint char_width, char_height; gint x, y; int allocated_width; int width, height; cairo_t *cr; GtkStyleContext *context; GdkRGBA fgcolorn; GdkRGBA bgcolorn; GdkRGBA fgcolors; GdkRGBA bgcolors; //Initializations priv = window->priv; cr = cairo_create (priv->ksurface); allocated_width = gtk_widget_get_allocated_width (GTK_WIDGET (priv->candidates)); context = gtk_widget_get_style_context (GTK_WIDGET (priv->candidates)); gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, &fgcolorn); gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, &bgcolorn); gtk_style_context_get_color (context, GTK_STATE_FLAG_SELECTED, &fgcolors); gtk_style_context_get_background_color (context, GTK_STATE_FLAG_SELECTED, &bgcolors); _kanjipadwindow_get_candidate_character_size (window, &char_width, &char_height); if (selected >= 0) { if (selected) cairo_set_source_rgba (cr, bgcolors.red, bgcolors.green, bgcolors.blue, 1.0); else cairo_set_source_rgba (cr, bgcolorn.red, bgcolorn.green, bgcolorn.blue, 1.0); x = 0; y = (char_height + 6) * index; width = allocated_width - 1; height = char_height + 5; cairo_rectangle (cr, x, y, width, height); cairo_fill (cr); } x = (allocated_width - char_width) / 2; y = (char_height + 6) * index + 3; cairo_translate(cr, x, y); string_utf = _kanjipadwindow_utf8_for_char (priv->kanji_candidates[index]); layout = gtk_widget_create_pango_layout (GTK_WIDGET (priv->candidates), string_utf); g_free (string_utf); if (selected >= 0 && selected) cairo_set_source_rgba (cr, fgcolors.red, fgcolors.green, fgcolors.blue, 1.0); else cairo_set_source_rgba (cr, fgcolorn.red, fgcolorn.green, fgcolorn.blue, 1.0); pango_cairo_update_layout (cr, layout); pango_cairo_show_layout (cr, layout); g_object_unref (layout); cairo_destroy (cr); }
static gboolean dt_iop_tonecurve_expose(GtkWidget *widget, GdkEventExpose *event, gpointer user_data) { dt_iop_module_t *self = (dt_iop_module_t *)user_data; dt_iop_tonecurve_gui_data_t *c = (dt_iop_tonecurve_gui_data_t *)self->gui_data; dt_iop_tonecurve_params_t *p = (dt_iop_tonecurve_params_t *)self->params; for(int k=0; k<6; k++) dt_draw_curve_set_point(c->minmax_curve, k, p->tonecurve_x[k], p->tonecurve_y[k]); 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; #if 0 // draw shadow around float alpha = 1.0f; for(int k=0; k<inset; k++) { cairo_rectangle(cr, -k, -k, width + 2*k, height + 2*k); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.6f; cairo_fill(cr); } #else 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); #endif cairo_set_source_rgb (cr, .3, .3, .3); cairo_rectangle(cr, 0, 0, width, height); cairo_fill(cr); if(c->mouse_y > 0 || c->dragging) { float oldx1, oldy1; oldx1 = p->tonecurve_x[c->selected]; oldy1 = p->tonecurve_y[c->selected]; if(c->selected == 0) dt_draw_curve_set_point(c->minmax_curve, 1, p->tonecurve_x[1], fmaxf(c->selected_min, p->tonecurve_y[1])); if(c->selected == 2) dt_draw_curve_set_point(c->minmax_curve, 1, p->tonecurve_x[1], fminf(c->selected_min, fmaxf(0.0, p->tonecurve_y[1] + DT_GUI_CURVE_INFL*(c->selected_min - oldy1)))); if(c->selected == 3) dt_draw_curve_set_point(c->minmax_curve, 4, p->tonecurve_x[4], fmaxf(c->selected_min, fminf(1.0, p->tonecurve_y[4] + DT_GUI_CURVE_INFL*(c->selected_min - oldy1)))); if(c->selected == 5) dt_draw_curve_set_point(c->minmax_curve, 4, p->tonecurve_x[4], fminf(c->selected_min, p->tonecurve_y[4])); dt_draw_curve_set_point(c->minmax_curve, c->selected, oldx1, c->selected_min); dt_draw_curve_calc_values(c->minmax_curve, 0.0, 1.0, DT_IOP_TONECURVE_RES, c->draw_min_xs, c->draw_min_ys); if(c->selected == 0) dt_draw_curve_set_point(c->minmax_curve, 1, p->tonecurve_x[1], fmaxf(c->selected_max, p->tonecurve_y[1])); if(c->selected == 2) dt_draw_curve_set_point(c->minmax_curve, 1, p->tonecurve_x[1], fminf(c->selected_max, fmaxf(0.0, p->tonecurve_y[1] + DT_GUI_CURVE_INFL*(c->selected_max - oldy1)))); if(c->selected == 3) dt_draw_curve_set_point(c->minmax_curve, 4, p->tonecurve_x[4], fmaxf(c->selected_max, fminf(1.0, p->tonecurve_y[4] + DT_GUI_CURVE_INFL*(c->selected_max - oldy1)))); if(c->selected == 5) dt_draw_curve_set_point(c->minmax_curve, 4, p->tonecurve_x[4], fminf(c->selected_max, p->tonecurve_y[4])); dt_draw_curve_set_point (c->minmax_curve, c->selected, oldx1, c->selected_max); dt_draw_curve_calc_values(c->minmax_curve, 0.0, 1.0, DT_IOP_TONECURVE_RES, c->draw_max_xs, c->draw_max_ys); } for(int k=0; k<6; k++) dt_draw_curve_set_point(c->minmax_curve, k, p->tonecurve_x[k], p->tonecurve_y[k]); dt_draw_curve_calc_values(c->minmax_curve, 0.0, 1.0, DT_IOP_TONECURVE_RES, c->draw_xs, c->draw_ys); // draw grid cairo_set_line_width(cr, .4); cairo_set_source_rgb (cr, .1, .1, .1); dt_draw_grid(cr, 4, 0, 0, width, height); // draw x positions cairo_set_line_width(cr, 1.); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); const float arrw = 7.0f; for(int k=1; k<5; k++) { cairo_move_to(cr, width*p->tonecurve_x[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->x_move == k) cairo_fill(cr); else cairo_stroke(cr); } // draw selected cursor cairo_set_line_width(cr, 1.); cairo_translate(cr, 0, height); // draw lum h istogram in background dt_develop_t *dev = darktable.develop; float *hist, hist_max; hist = dev->histogram_pre_tonecurve; hist_max = dev->histogram_pre_tonecurve_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); } if(c->mouse_y > 0 || c->dragging) { // draw min/max, if selected cairo_set_source_rgba(cr, .6, .6, .6, .5); cairo_move_to(cr, 0, - height*c->draw_min_ys[0]); for(int k=1; k<DT_IOP_TONECURVE_RES; k++) cairo_line_to(cr, k*width/(DT_IOP_TONECURVE_RES-1.0), - height*c->draw_min_ys[k]); cairo_line_to(cr, width, - height*c->draw_min_ys[DT_IOP_TONECURVE_RES-1]); cairo_line_to(cr, width, - height*c->draw_max_ys[DT_IOP_TONECURVE_RES-1]); for(int k=DT_IOP_TONECURVE_RES-2; k>=0; k--) cairo_line_to(cr, k*width/(DT_IOP_TONECURVE_RES-1.0), - height*c->draw_max_ys[k]); cairo_close_path(cr); cairo_fill(cr); // draw mouse focus circle cairo_set_source_rgb(cr, .9, .9, .9); const float pos = MAX(0, (DT_IOP_TONECURVE_RES-1) * c->mouse_x/(float)width - 1); int k = (int)pos; const float f = k - pos; if(k >= DT_IOP_TONECURVE_RES-1) k = DT_IOP_TONECURVE_RES - 2; float ht = -height*(f*c->draw_ys[k] + (1-f)*c->draw_ys[k+1]); cairo_arc(cr, c->mouse_x, ht, 4, 0, 2.*M_PI); cairo_stroke(cr); } // draw curve cairo_set_line_width(cr, 2.); cairo_set_source_rgb(cr, .9, .9, .9); // cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_move_to(cr, 0, -height*c->draw_ys[0]); for(int k=1; k<DT_IOP_TONECURVE_RES; k++) cairo_line_to(cr, k*width/(DT_IOP_TONECURVE_RES-1.0), - height*c->draw_ys[k]); cairo_stroke(cr); 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; }
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % % % % % R e a d P A N G O I m a g e % % % % % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % ReadPANGOImage() reads an image in the Pango Markup Language Format. % % The format of the ReadPANGOImage method is: % % Image *ReadPANGOImage(const ImageInfo *image_info, % ExceptionInfo *exception) % % A description of each parameter follows: % % o image_info: the image info. % % o exception: return any errors or warnings in this structure. % */ static Image *ReadPANGOImage(const ImageInfo *image_info, ExceptionInfo *exception) { cairo_font_options_t *font_options; cairo_surface_t *surface; char *caption, *property; cairo_t *cairo_image; const char *option; DrawInfo *draw_info; Image *image; MagickBooleanType status; PangoAlignment align; PangoContext *context; PangoFontMap *fontmap; PangoGravity gravity; PangoLayout *layout; PangoRectangle extent; PixelInfo fill_color; RectangleInfo page; register unsigned char *p; size_t stride; ssize_t y; unsigned char *pixels; /* Initialize Image structure. */ assert(image_info != (const ImageInfo *) NULL); assert(image_info->signature == MagickSignature); if (image_info->debug != MagickFalse) (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", image_info->filename); assert(exception != (ExceptionInfo *) NULL); assert(exception->signature == MagickSignature); image=AcquireImage(image_info,exception); (void) ResetImagePage(image,"0x0+0+0"); /* Format caption. */ option=GetImageArtifact(image,"filename"); if (option == (const char *) NULL) property=InterpretImageProperties(image_info,image,image_info->filename, exception); else if (LocaleNCompare(option,"pango:",6) == 0) property=InterpretImageProperties(image_info,image,option+6,exception); else property=InterpretImageProperties(image_info,image,option,exception); (void) SetImageProperty(image,"caption",property,exception); property=DestroyString(property); caption=ConstantString(GetImageProperty(image,"caption",exception)); /* Get context. */ fontmap=pango_cairo_font_map_new(); pango_cairo_font_map_set_resolution(PANGO_CAIRO_FONT_MAP(fontmap), image->resolution.x == 0.0 ? 90.0 : image->resolution.x); font_options=cairo_font_options_create(); option=GetImageArtifact(image,"pango:hinting"); if (option != (const char *) NULL) { if (LocaleCompare(option,"none") != 0) cairo_font_options_set_hint_style(font_options,CAIRO_HINT_STYLE_NONE); if (LocaleCompare(option,"full") != 0) cairo_font_options_set_hint_style(font_options,CAIRO_HINT_STYLE_FULL); } context=pango_font_map_create_context(fontmap); pango_cairo_context_set_font_options(context,font_options); cairo_font_options_destroy(font_options); option=GetImageArtifact(image,"pango:language"); if (option != (const char *) NULL) pango_context_set_language(context,pango_language_from_string(option)); draw_info=CloneDrawInfo(image_info,(DrawInfo *) NULL); pango_context_set_base_dir(context,draw_info->direction == RightToLeftDirection ? PANGO_DIRECTION_RTL : PANGO_DIRECTION_LTR); switch (draw_info->gravity) { case NorthGravity: { gravity=PANGO_GRAVITY_NORTH; break; } case NorthWestGravity: case WestGravity: case SouthWestGravity: { gravity=PANGO_GRAVITY_WEST; break; } case NorthEastGravity: case EastGravity: case SouthEastGravity: { gravity=PANGO_GRAVITY_EAST; break; } case SouthGravity: { gravity=PANGO_GRAVITY_SOUTH; break; } default: { gravity=PANGO_GRAVITY_AUTO; break; } } pango_context_set_base_gravity(context,gravity); option=GetImageArtifact(image,"pango:gravity-hint"); if (option != (const char *) NULL) { if (LocaleCompare(option,"line") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_LINE); if (LocaleCompare(option,"natural") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_NATURAL); if (LocaleCompare(option,"strong") == 0) pango_context_set_gravity_hint(context,PANGO_GRAVITY_HINT_STRONG); } /* Configure layout. */ layout=pango_layout_new(context); option=GetImageArtifact(image,"pango:auto-dir"); if (option != (const char *) NULL) pango_layout_set_auto_dir(layout,1); option=GetImageArtifact(image,"pango:ellipsize"); if (option != (const char *) NULL) { if (LocaleCompare(option,"end") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_END); if (LocaleCompare(option,"middle") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_MIDDLE); if (LocaleCompare(option,"none") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_NONE); if (LocaleCompare(option,"start") == 0) pango_layout_set_ellipsize(layout,PANGO_ELLIPSIZE_START); } option=GetImageArtifact(image,"pango:justify"); if (IfMagickTrue(IsStringTrue(option))) pango_layout_set_justify(layout,1); option=GetImageArtifact(image,"pango:single-paragraph"); if (IfMagickTrue(IsStringTrue(option))) pango_layout_set_single_paragraph_mode(layout,1); option=GetImageArtifact(image,"pango:wrap"); if (option != (const char *) NULL) { if (LocaleCompare(option,"char") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_CHAR); if (LocaleCompare(option,"word") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_WORD); if (LocaleCompare(option,"word-char") == 0) pango_layout_set_wrap(layout,PANGO_WRAP_WORD_CHAR); } option=GetImageArtifact(image,"pango:indent"); if (option != (const char *) NULL) pango_layout_set_indent(layout,(int) ((StringToLong(option)* (image->resolution.x == 0.0 ? 90.0 : image->resolution.x)*PANGO_SCALE+36)/ 90.0+0.5)); switch (draw_info->align) { case CenterAlign: align=PANGO_ALIGN_CENTER; break; case RightAlign: align=PANGO_ALIGN_RIGHT; break; case LeftAlign: align=PANGO_ALIGN_LEFT; break; default: { if (draw_info->gravity == CenterGravity) { align=PANGO_ALIGN_CENTER; break; } align=PANGO_ALIGN_LEFT; break; } } if ((align != PANGO_ALIGN_CENTER) && (draw_info->direction == RightToLeftDirection)) align=(PangoAlignment) (PANGO_ALIGN_LEFT+PANGO_ALIGN_RIGHT-align); pango_layout_set_alignment(layout,align); if (draw_info->font != (char *) NULL) { PangoFontDescription *description; /* Set font. */ description=pango_font_description_from_string(draw_info->font); pango_font_description_set_size(description,(int) (PANGO_SCALE* draw_info->pointsize+0.5)); pango_layout_set_font_description(layout,description); pango_font_description_free(description); } option=GetImageArtifact(image,"pango:markup"); if ((option != (const char *) NULL) && (IsStringTrue(option) == MagickFalse)) pango_layout_set_text(layout,caption,-1); else { GError *error; error=(GError *) NULL; if (pango_parse_markup(caption,-1,0,NULL,NULL,NULL,&error) == 0) (void) ThrowMagickException(exception,GetMagickModule(),CoderError, error->message,"`%s'",image_info->filename); pango_layout_set_markup(layout,caption,-1); } pango_layout_context_changed(layout); page.x=0; page.y=0; if (image_info->page != (char *) NULL) (void) ParseAbsoluteGeometry(image_info->page,&page); if (image->columns == 0) { pango_layout_get_extents(layout,NULL,&extent); image->columns=(extent.x+extent.width+PANGO_SCALE/2)/PANGO_SCALE+2*page.x; } else { image->columns-=2*page.x; pango_layout_set_width(layout,(int) ((PANGO_SCALE*image->columns* (image->resolution.x == 0.0 ? 90.0 : image->resolution.x)+45.0)/90.0+ 0.5)); } if (image->rows == 0) { pango_layout_get_extents(layout,NULL,&extent); image->rows=(extent.y+extent.height+PANGO_SCALE/2)/PANGO_SCALE+2*page.y; } else { image->rows-=2*page.y; pango_layout_set_height(layout,(int) ((PANGO_SCALE*image->rows* (image->resolution.y == 0.0 ? 90.0 : image->resolution.y)+45.0)/90.0+ 0.5)); } /* Render markup. */ stride=(size_t) cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, image->columns); pixels=(unsigned char *) AcquireQuantumMemory(image->rows,stride* sizeof(*pixels)); if (pixels == (unsigned char *) NULL) { draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); } surface=cairo_image_surface_create_for_data(pixels,CAIRO_FORMAT_ARGB32, image->columns,image->rows,stride); cairo_image=cairo_create(surface); cairo_set_operator(cairo_image,CAIRO_OPERATOR_CLEAR); cairo_paint(cairo_image); cairo_set_operator(cairo_image,CAIRO_OPERATOR_OVER); cairo_translate(cairo_image,page.x,page.y); pango_cairo_show_layout(cairo_image,layout); cairo_destroy(cairo_image); cairo_surface_destroy(surface); g_object_unref(layout); g_object_unref(fontmap); /* Convert surface to image. */ (void) SetImageBackgroundColor(image,exception); p=pixels; GetPixelInfo(image,&fill_color); for (y=0; y < (ssize_t) image->rows; y++) { register Quantum *q; register ssize_t x; q=GetAuthenticPixels(image,0,y,image->columns,1,exception); if (q == (Quantum *) NULL) break; for (x=0; x < (ssize_t) image->columns; x++) { double gamma; fill_color.blue=(double) ScaleCharToQuantum(*p++); fill_color.green=(double) ScaleCharToQuantum(*p++); fill_color.red=(double) ScaleCharToQuantum(*p++); fill_color.alpha=(double) ScaleCharToQuantum(*p++); /* Disassociate alpha. */ gamma=1.0-QuantumScale*fill_color.alpha; gamma=PerceptibleReciprocal(gamma); fill_color.blue*=gamma; fill_color.green*=gamma; fill_color.red*=gamma; CompositePixelOver(image,&fill_color,fill_color.alpha,q,(double) GetPixelAlpha(image,q),q); q+=GetPixelChannels(image); } if (SyncAuthenticPixels(image,exception) == MagickFalse) break; if (image->previous == (Image *) NULL) { status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y, image->rows); if (status == MagickFalse) break; } } /* Relinquish resources. */ pixels=(unsigned char *) RelinquishMagickMemory(pixels); draw_info=DestroyDrawInfo(draw_info); caption=DestroyString(caption); return(GetFirstImageInList(image)); }
static void gtk_css_image_radial_draw (GtkCssImage *image, cairo_t *cr, double width, double height) { GtkCssImageRadial *radial = GTK_CSS_IMAGE_RADIAL (image); cairo_pattern_t *pattern; cairo_matrix_t matrix; double x, y; double radius, yscale; double start, end; double r1, r2, r3, r4, r; double offset; int i, last; x = _gtk_css_position_value_get_x (radial->position, width); y = _gtk_css_position_value_get_y (radial->position, height); if (radial->circle) { switch (radial->size) { case GTK_CSS_EXPLICIT_SIZE: radius = _gtk_css_number_value_get (radial->sizes[0], width); break; case GTK_CSS_CLOSEST_SIDE: radius = MIN (MIN (x, width - x), MIN (y, height - y)); break; case GTK_CSS_FARTHEST_SIDE: radius = MAX (MAX (x, width - x), MAX (y, height - y)); break; case GTK_CSS_CLOSEST_CORNER: case GTK_CSS_FARTHEST_CORNER: r1 = x*x + y*y; r2 = x*x + (height - y)*(height - y); r3 = (width - x)*(width - x) + y*y; r4 = (width - x)*(width - x) + (height - y)*(height - y); if (radial->size == GTK_CSS_CLOSEST_CORNER) r = MIN ( MIN (r1, r2), MIN (r3, r4)); else r = MAX ( MAX (r1, r2), MAX (r3, r4)); radius = sqrt (r); break; default: g_assert_not_reached (); } radius = MAX (1.0, radius); yscale = 1.0; } else { double hradius, vradius; switch (radial->size) { case GTK_CSS_EXPLICIT_SIZE: hradius = _gtk_css_number_value_get (radial->sizes[0], width); vradius = _gtk_css_number_value_get (radial->sizes[1], height); break; case GTK_CSS_CLOSEST_SIDE: hradius = MIN (x, width - x); vradius = MIN (y, height - y); break; case GTK_CSS_FARTHEST_SIDE: hradius = MAX (x, width - x); vradius = MAX (y, height - y); break; case GTK_CSS_CLOSEST_CORNER: hradius = M_SQRT2 * MIN (x, width - x); vradius = M_SQRT2 * MIN (y, height - y); break; case GTK_CSS_FARTHEST_CORNER: hradius = M_SQRT2 * MAX (x, width - x); vradius = M_SQRT2 * MAX (y, height - y); break; default: g_assert_not_reached (); } hradius = MAX (1.0, hradius); vradius = MAX (1.0, vradius); radius = hradius; yscale = vradius / hradius; } gtk_css_image_radial_get_start_end (radial, radius, &start, &end); pattern = cairo_pattern_create_radial (0, 0, 0, 0, 0, radius); if (yscale != 1.0) { cairo_matrix_init_scale (&matrix, 1.0, 1.0 / yscale); cairo_pattern_set_matrix (pattern, &matrix); } if (radial->repeating) cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT); else cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD); offset = start; last = -1; for (i = 0; i < radial->stops->len; i++) { GtkCssImageRadialColorStop *stop; double pos, step; stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, i); if (stop->offset == NULL) { if (i == 0) pos = 0.0; else if (i + 1 == radial->stops->len) pos = 1.0; else continue; } else pos = _gtk_css_number_value_get (stop->offset, radius) / radius; pos = MAX (pos, 0); step = pos / (i - last); for (last = last + 1; last <= i; last++) { const GdkRGBA *rgba; stop = &g_array_index (radial->stops, GtkCssImageRadialColorStop, last); rgba = _gtk_css_rgba_value_get_rgba (stop->color); offset += step; cairo_pattern_add_color_stop_rgba (pattern, (offset - start) / (end - start), rgba->red, rgba->green, rgba->blue, rgba->alpha); } offset = pos; last = i; } cairo_rectangle (cr, 0, 0, width, height); cairo_translate (cr, x, y); cairo_set_source (cr, pattern); cairo_fill (cr); cairo_pattern_destroy (pattern); }
static gboolean dt_iop_zonesystem_preview_expose (GtkWidget *widget, GdkEventExpose *event, dt_iop_module_t *self) { const int inset = 2; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width, height = allocation.height; 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; cairo_surface_t *cst = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); /* clear background */ GtkStateType state = gtk_widget_get_state(self->expander); GtkStyle *style = gtk_widget_get_style(self->expander); cairo_set_source_rgb (cr, style->bg[state].red/65535.0, style->bg[state].green/65535.0, style->bg[state].blue/65535.0); cairo_paint (cr); width -= 2*inset; height -= 2*inset; cairo_translate(cr, inset, inset); dt_pthread_mutex_lock(&g->lock); if( g->in_preview_buffer && g->out_preview_buffer && self->enabled) { /* calculate the zonemap */ float zonemap[MAX_ZONE_SYSTEM_SIZE]= {-1}; _iop_zonesystem_calculate_zonemap (p,zonemap); /* let's generate a pixbuf from pixel zone buffer */ guchar *image = g_malloc ((g->preview_width*g->preview_height)*4); guchar *buffer = g->mouse_over_output_zones ? g->out_preview_buffer : g->in_preview_buffer; for (int k=0; k<g->preview_width*g->preview_height; k++) { int zone = 255*CLIP (((1.0/(p->size-1))*buffer[k])); image[4*k+2] = (g->hilite_zone && buffer[k]==g->zone_under_mouse)?255:zone; image[4*k+1] = (g->hilite_zone && buffer[k]==g->zone_under_mouse)?255:zone; image[4*k+0] = (g->hilite_zone && buffer[k]==g->zone_under_mouse)?0:zone; } dt_pthread_mutex_unlock(&g->lock); const int wd = g->preview_width, ht = g->preview_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 (image, 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); cairo_rectangle(cr, 1, 1, wd-2, ht-2); cairo_set_source_surface (cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_GOOD); cairo_fill_preserve(cr); cairo_surface_destroy (surface); cairo_set_line_width(cr, 1.0); cairo_set_source_rgb(cr, .1, .1, .1); cairo_stroke(cr); g_free(image); } else dt_pthread_mutex_unlock(&g->lock); 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 _cairo_render_background (CairoRenderer *renderer, PinPointPoint *point) { char *full_path = NULL; const char *file; if (point == NULL) return; file = point->bg; if (point->bg_type != PP_BG_COLOR && renderer->path && file) { char *dir = g_path_get_dirname (renderer->path); full_path = g_build_filename (dir, file, NULL); g_free (dir); file = full_path; } if (point->stage_color) { ClutterColor color; clutter_color_from_string (&color, point->stage_color); cairo_set_source_rgba (renderer->ctx, color.red / 255.f, color.green / 255.f, color.blue / 255.f, color.alpha / 255.f); cairo_paint (renderer->ctx); } switch (point->bg_type) { case PP_BG_NONE: break; case PP_BG_COLOR: { ClutterColor color; clutter_color_from_string (&color, point->bg); cairo_set_source_rgba (renderer->ctx, color.red / 255.f, color.green / 255.f, color.blue / 255.f, color.alpha / 255.f); cairo_paint (renderer->ctx); } break; case PP_BG_IMAGE: { cairo_surface_t *surface; float bg_x, bg_y, bg_width, bg_height, bg_scale_x, bg_scale_y; surface = _cairo_get_surface (renderer, file); if (surface == NULL) break; bg_width = cairo_image_surface_get_width (surface); bg_height = cairo_image_surface_get_height (surface); pp_get_background_position_scale (point, renderer->width, renderer->height, bg_width, bg_height, &bg_x, &bg_y, &bg_scale_x, &bg_scale_y); cairo_save (renderer->ctx); cairo_translate (renderer->ctx, bg_x, bg_y); cairo_scale (renderer->ctx, bg_scale_x, bg_scale_y); cairo_set_source_surface (renderer->ctx, surface, 0., 0.); cairo_paint (renderer->ctx); cairo_restore (renderer->ctx); } break; case PP_BG_VIDEO: { #ifdef USE_CLUTTER_GST GdkPixbuf *pixbuf; cairo_surface_t *surface; float bg_x, bg_y, bg_width, bg_height, bg_scale_x, bg_scale_y; GCancellable* cancellable = g_cancellable_new (); GFile *abs_file; gchar *abs_path; abs_file = g_file_resolve_relative_path (pp_basedir, point->bg); abs_path = g_file_get_path (abs_file); g_object_unref (abs_file); pixbuf = gst_video_thumbnailer_get_shot (abs_path, cancellable); g_free (abs_path); if (pixbuf == NULL) { g_warning ("Could not create video thumbmail for %s", point->bg); break; } surface = _cairo_new_surface_from_pixbuf (pixbuf); g_hash_table_insert (renderer->surfaces, g_strdup (file), surface); bg_width = cairo_image_surface_get_width (surface); bg_height = cairo_image_surface_get_height (surface); pp_get_background_position_scale (point, renderer->width, A4_LS_HEIGHT, bg_width, bg_height, &bg_x, &bg_y, &bg_scale_x, &bg_scale_y); cairo_save (renderer->ctx); cairo_translate (renderer->ctx, bg_x, bg_y); cairo_scale (renderer->ctx, bg_scale_x, bg_scale_y); cairo_set_source_surface (renderer->ctx, surface, 0., 0.); cairo_paint (renderer->ctx); cairo_restore (renderer->ctx); #endif break; } case PP_BG_SVG: #ifdef HAVE_RSVG { RsvgHandle *svg = _cairo_get_svg (renderer, file); RsvgDimensionData dim; float bg_x, bg_y, bg_scale_x, bg_scale_y; if (svg == NULL) break; rsvg_handle_get_dimensions (svg, &dim); pp_get_background_position_scale (point, renderer->width, renderer->height, dim.width, dim.height, &bg_x, &bg_y, &bg_scale_x, &bg_scale_y); cairo_save (renderer->ctx); cairo_translate (renderer->ctx, bg_x, bg_y); cairo_scale (renderer->ctx, bg_scale_x, bg_scale_y); rsvg_handle_render_cairo (svg, renderer->ctx); cairo_restore (renderer->ctx); } #endif break; case PP_BG_CAMERA: /* silently ignore camera backgrounds */ break; default: g_assert_not_reached(); } g_free (full_path); }
void process (struct dt_iop_module_t *self, dt_dev_pixelpipe_iop_t *piece, void *ivoid, void *ovoid, const dt_iop_roi_t *roi_in, const dt_iop_roi_t *roi_out) { dt_iop_watermark_data_t *data = (dt_iop_watermark_data_t *)piece->data; float *in = (float *)ivoid; float *out = (float *)ovoid; const int ch = piece->colors; /* Load svg if not loaded */ gchar *svgdoc = _watermark_get_svgdoc (self, data, &piece->pipe->image); if (!svgdoc) { memcpy(ovoid, ivoid, (size_t)sizeof(float)*ch*roi_out->width*roi_out->height); return; } /* create the rsvghandle from parsed svg data */ GError *error = NULL; RsvgHandle *svg = rsvg_handle_new_from_data ((const guint8 *)svgdoc,strlen (svgdoc),&error); g_free (svgdoc); if (!svg || error) { memcpy(ovoid, ivoid, (size_t)sizeof(float)*ch*roi_out->width*roi_out->height); return; } /* setup stride for performance */ int stride = cairo_format_stride_for_width (CAIRO_FORMAT_ARGB32,roi_out->width); /* create cairo memory surface */ guint8 *image= (guint8 *)g_malloc (stride*roi_out->height); memset (image,0,(size_t)stride*roi_out->height); cairo_surface_t *surface = cairo_image_surface_create_for_data (image,CAIRO_FORMAT_ARGB32,roi_out->width,roi_out->height,stride); if (cairo_surface_status(surface)!= CAIRO_STATUS_SUCCESS) { // fprintf(stderr,"Cairo surface error: %s\n",cairo_status_to_string(cairo_surface_status(surface))); g_free (image); memcpy(ovoid, ivoid, (size_t)sizeof(float)*ch*roi_out->width*roi_out->height); return; } /* create cairo context and setup transformation/scale */ cairo_t *cr = cairo_create (surface); /* get the dimension of svg */ RsvgDimensionData dimension; rsvg_handle_get_dimensions (svg,&dimension); // width/height of current (possibly cropped) image const float iw = piece->buf_in.width; const float ih = piece->buf_in.height; const float uscale = data->scale / 100.0; // user scale, from GUI in percent // wbase, hbase are the base width and height, this is the multiplicator used for the offset computing // scale is the scale of the watermark itself and is used only to render it. float wbase, hbase, scale; if (data->sizeto == DT_SCALE_IMAGE) { // in image mode, the wbase and hbase are just the image width and height wbase = iw; hbase = ih; if (dimension.width>dimension.height) scale = (iw*roi_out->scale)/dimension.width; else scale = (ih*roi_out->scale)/dimension.height; } else { // in larger/smaller side mode, set wbase and hbase to the largest or smallest side of the image float larger; if (dimension.width > dimension.height) larger = (float)dimension.width; else larger = (float)dimension.height; if (iw>ih) { wbase = hbase = (data->sizeto==DT_SCALE_LARGER_BORDER)?iw:ih; scale = (data->sizeto==DT_SCALE_LARGER_BORDER)?(iw/larger):(ih/larger); } else { wbase = hbase = (data->sizeto==DT_SCALE_SMALLER_BORDER)?iw:ih; scale = (data->sizeto==DT_SCALE_SMALLER_BORDER)?(iw/larger):(ih/larger); } scale *= roi_out->scale; } scale *= uscale; // compute the width and height of the SVG object in image dimension. This is only used to properly // layout the watermark based on the alignment. float svg_width, svg_height; if (dimension.width>dimension.height) { if (data->sizeto==DT_SCALE_IMAGE || (iw>ih && data->sizeto==DT_SCALE_LARGER_BORDER) || (iw<ih && data->sizeto==DT_SCALE_SMALLER_BORDER)) { svg_width = iw * uscale; svg_height = dimension.height * (svg_width / dimension.width); } else { svg_width = ih * uscale; svg_height = dimension.height * (svg_width / dimension.width); } } else { if (data->sizeto==DT_SCALE_IMAGE || (ih>iw && data->sizeto==DT_SCALE_LARGER_BORDER) || (ih<iw && data->sizeto==DT_SCALE_SMALLER_BORDER)) { svg_height = ih * uscale; svg_width = dimension.width * (svg_height / dimension.height ); } else { svg_height = iw * uscale; svg_width = dimension.width * (svg_height / dimension.height); } } // compute translation for the given alignment in image dimension float ty=0,tx=0; if( data->alignment >=0 && data->alignment <3) // Align to verttop ty=0; else if( data->alignment >=3 && data->alignment <6) // Align to vertcenter ty=(ih/2.0)-(svg_height/2.0); else if( data->alignment >=6 && data->alignment <9) // Align to vertbottom ty=ih-svg_height; if( data->alignment == 0 || data->alignment == 3 || data->alignment==6 ) tx=0; else if( data->alignment == 1 || data->alignment == 4 || data->alignment==7 ) tx=(iw/2.0)-(svg_width/2.0); else if( data->alignment == 2 || data->alignment == 5 || data->alignment==8 ) tx=iw-svg_width; // translate to position cairo_translate (cr,-roi_in->x,-roi_in->y); // add translation for the given value in GUI (xoffset,yoffset) tx += data->xoffset*wbase; ty += data->yoffset*hbase; cairo_translate (cr,tx*roi_out->scale,ty*roi_out->scale); // now set proper scale for the watermark itself cairo_scale(cr, scale, scale); /* render svg into surface*/ dt_pthread_mutex_lock(&darktable.plugin_threadsafe); rsvg_handle_render_cairo (svg,cr); dt_pthread_mutex_unlock(&darktable.plugin_threadsafe); /* ensure that all operations on surface finishing up */ cairo_surface_flush (surface); /* render surface on output */ guint8 *sd = image; float opacity = data->opacity/100.0; /* #ifdef _OPENMP #pragma omp parallel for default(none) shared(roi_out, in, out,sd,opacity) schedule(static) #endif */ for(int j=0; j<roi_out->height; j++) for(int i=0; i<roi_out->width; i++) { float alpha = (sd[3]/255.0)*opacity; /* svg uses a premultiplied alpha, so only use opacity for the blending */ out[0] = ((1.0-alpha)*in[0]) + (opacity*(sd[2]/255.0)); out[1] = ((1.0-alpha)*in[1]) + (opacity*(sd[1]/255.0)); out[2] = ((1.0-alpha)*in[2]) + (opacity*(sd[0]/255.0)); out[3] = in[3]; out+=ch; in+=ch; sd+=4; } /* clean up */ cairo_surface_destroy (surface); g_object_unref (svg); g_free (image); }
bool TextAsset::load() { // Set up a temporary Cairo surface/context for text measurement cairo_surface_t* probeSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1); if (cairo_surface_status(probeSurface) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo surface\n"); _error = true; return false; } cairo_t* probeContext = cairo_create(probeSurface); if (cairo_status(probeContext) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo context\n"); _error = true; return false; } // Text rectangle drawn within border const int idealWidth = _maxSize.width - _marginLeft - _marginRight; const Size textRegion(idealWidth, _maxSize.height - _marginTop - _marginBottom); const float fontSize = primaryFontSize(probeContext, textRegion); const std::string fontDesc = _fontName + " " + boost::lexical_cast<std::string>(fontSize); PangoFontDescription* fontDescription = pango_font_description_from_string(fontDesc.c_str()); const std::string req_desc_str(pango_font_description_to_string(fontDescription)); PangoFontMap* fontMap = pango_cairo_font_map_new_for_font_type(CAIRO_FONT_TYPE_FT); PangoContext* pango_context = pango_font_map_create_context(fontMap); // TODO: Does this need to be freed or does the context take it with it? PangoFont* pangoFont = pango_font_map_load_font(fontMap, pango_context, fontDescription); PangoFontDescription* reverseDescription = pango_font_describe(pangoFont); const std::string match_desc_str(pango_font_description_to_string(reverseDescription)); pango_font_description_free(reverseDescription); g_object_unref(pango_context); if (req_desc_str.find(match_desc_str) == std::string::npos) { fprintf(stderr, "Warning: Unable to correctly match font \"%s\", using " "\"%s\" instead.\n", req_desc_str.c_str(), match_desc_str.c_str()); } float shadowXOffset = 0; float shadowYOffset = 0; if (_dropShadow) { shadowXOffset = _dropShadowOffset.x() * CLIENT_TO_SERVER_SCALE * fontSize; shadowYOffset = _dropShadowOffset.y() * CLIENT_TO_SERVER_SCALE * fontSize; } Rect tight; const Size textSize = computeSizeOfText(probeContext, _textContent, idealWidth, fontDescription, &tight); const Size imageSize = imageSizeForTextSize(tight.size, shadowXOffset, shadowYOffset); // Tear down scratch contexts cairo_destroy(probeContext); cairo_surface_destroy(probeSurface); const int width = imageSize.width; const int height = imageSize.height; // Configure the actual Cairo drawing surface/context now that we know the final resolution cairo_surface_t* cairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); if (cairo_surface_status(cairoSurface) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo surface\n"); _error = true; return false; } cairo_t* cairoContext = cairo_create(cairoSurface); // Flip the context like in the iOS version. // This fixes flipped filters associated with text assets. cairo_translate(cairoContext, 0.0, height); cairo_scale(cairoContext, 1.0, -1.0); if (cairo_status(cairoContext) != CAIRO_STATUS_SUCCESS) { fprintf(stderr, "Could not create Cairo context\n"); _error = true; return false; } // Fill the box with the background color cairo_save(cairoContext); cairo_set_operator(cairoContext, CAIRO_OPERATOR_SOURCE); const mf::Color& bgColor(_style->getBackgroundColor()); cairo_set_source_rgba(cairoContext, bgColor.red, bgColor.green, bgColor.blue, bgColor.alpha); if (_shape == 0) { if (_cornerWidth > 0 && _cornerHeight > 0) { // TODO: Support independent corner width and height drawRoundedRect(cairoContext, 0, 0, imageSize.width, imageSize.height, _cornerWidth); } else { cairo_paint(cairoContext); if (_strokeThickness > 0.0f) { drawStrokedRect(cairoContext, 0, 0, imageSize.width, imageSize.height, _strokeThickness); } } } else if (_shape == 1) { strokeFillBezier(cairoContext, 0, 0, imageSize.width, imageSize.height, _strokeThickness); } cairo_restore(cairoContext); const Rect textRect = textRectForTextSize(textSize, imageSize, tight); if (_dropShadow) { const Rect shadowRect(textRect.x + shadowXOffset, textRect.y + shadowYOffset, textRect.size.width, textRect.size.height); cairo_set_source_rgba(cairoContext, _dropShadowColor.red, _dropShadowColor.green, _dropShadowColor.blue, _dropShadowColor.alpha); drawText(cairoContext, _textContent, shadowRect, fontDescription, false); } cairo_set_source_rgba(cairoContext, _textColor.red, _textColor.green, _textColor.blue, _textColor.alpha); if (_textColor.alpha > 0.0) { drawText(cairoContext, _textContent, textRect, fontDescription, true); } // DEBUG: Dump rendered text to an image // cairo_surface_write_to_png(cairoSurface, "text.png"); // Transfer Cairo surface to OpenGL texture GLubyte* imageData = static_cast<GLubyte *>(cairo_image_surface_get_data(cairoSurface)); glGenTextures(1, &_texture.textureID); glBindTexture(GL_TEXTURE_2D, _texture.textureID); _texture.width = width; _texture.height = height; _texture.s = 1.0; _texture.t = 1.0; _texture.aspect = static_cast<GLfloat>(_texture.width) / _texture.height; _texture.flipImage = true; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); #ifdef GL_BGRA // Allocate and transfer data into texture (allow OpenGL swizzling) glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, imageData); #else // Cairo uses a BGRA layout, OpenGL ES 2.0 does not support GL_BGRA as a // source format so manually perform swizzling. for (size_t i = 0; i < width * height * BYTES_PER_PIXEL; i += BYTES_PER_PIXEL) { std::swap(imageData[i], imageData[i + 2]); } // Allocate and transfer data into texture glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, imageData); #endif // Clean up pango_font_description_free(fontDescription); cairo_destroy(cairoContext); cairo_surface_destroy(cairoSurface); g_object_unref(pangoFont); _loading = false; _loaded = !_loading && !_error; return true; }
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; }
int renderGlyphsCairo(imageObj *img,double x, double y, labelStyleObj *style, char *text) { cairo_renderer *r = CAIRO_RENDERER(img); cairoCacheData *cache = MS_IMAGE_RENDERER_CACHE(img); faceCacheObj *face = getFontFace(cache,style->font); char *utfptr=text; int i,has_kerning,unicode; unsigned long previdx=0; int numglyphs = msGetNumGlyphs(text); cairo_glyph_t glyph; cairo_text_extents_t extents; double px=0,py=0; if(face == NULL) { return MS_FAILURE; } cairo_set_font_face(r->cr,face->face); cairo_set_font_size(r->cr,style->size*96/72.0); cairo_save(r->cr); cairo_translate(r->cr,MS_NINT(x),MS_NINT(y)); if(style->rotation != 0.0) cairo_rotate(r->cr, -style->rotation); has_kerning = FT_HAS_KERNING((face->ftface)); for(i=0;i<numglyphs;i++) { utfptr+=msUTF8ToUniChar(utfptr, &unicode); glyph.x=px; glyph.y=py; if(unicode=='\n') { py += ceil(style->size*CAIROLINESPACE); px = 0; previdx=0; continue; } glyph.index = FT_Get_Char_Index(face->ftface, unicode); if( has_kerning && previdx ) { FT_Vector delta; FT_Get_Kerning( face->ftface, previdx, glyph.index, FT_KERNING_DEFAULT, &delta ); px += delta.x / 64.; } cairo_glyph_extents(r->cr,&glyph,1,&extents); cairo_glyph_path(r->cr,&glyph,1); px += extents.x_advance; previdx=glyph.index; } if (style->outlinewidth > 0) { cairo_save(r->cr); msCairoSetSourceColor(r->cr, style->outlinecolor); cairo_set_line_width(r->cr, style->outlinewidth + 1); cairo_stroke_preserve(r->cr); cairo_restore(r->cr); } if(style->color) { msCairoSetSourceColor(r->cr, style->color); cairo_fill(r->cr); } cairo_new_path(r->cr); cairo_restore(r->cr); return MS_SUCCESS; }
static gboolean gtk_xournal_expose(GtkWidget* widget, GdkEventExpose* event) { g_return_val_if_fail(widget != NULL, FALSE); g_return_val_if_fail(GTK_IS_XOURNAL(widget), FALSE); g_return_val_if_fail(event != NULL, FALSE); GtkXournal* xournal = GTK_XOURNAL(widget); gdk_threads_enter(); cairo_t* cr = gdk_cairo_create(GTK_WIDGET(widget)->window); ArrayIterator<PageView*> it = xournal->view->pageViewIterator(); GtkAllocation alloc = { 0 }; gtk_widget_get_allocation(widget, &alloc); int lastVisibleX = alloc.width + xournal->x + 10; int lastVisibleY = alloc.height + xournal->y + 10; //+10 fix to draw the shadow int firstVisibleX = xournal->x - 10; int firstVisibleY = xournal->y - 10; while (it.hasNext()) { PageView* pv = it.next(); int px = pv->getX(); int py = pv->getY(); int pw = pv->getDisplayWidth(); int ph = pv->getDisplayHeight(); // not visible, its on the right side of the visible area if (px > lastVisibleX) { continue; } // not visible, its on the left side of the visible area if (px + pw < firstVisibleX) { continue; } // not visible, its on the bottom side of the visible area if (py > lastVisibleY) { continue; } // not visible, its on the top side of the visible area if (py + ph < firstVisibleY) { continue; } int x = px - xournal->x; int y = py - xournal->y; gtk_xournal_draw_shadow(xournal, cr, x, y, pw, ph, pv->isSelected()); cairo_save(cr); cairo_translate(cr, x, y); GdkRectangle rect = event->area; rect.x -= x; rect.y -= y; pv->paintPage(cr, &rect); cairo_restore(cr); } if (xournal->selection) { double zoom = xournal->view->getZoom(); int px = xournal->selection->getXOnView() * zoom; int py = xournal->selection->getYOnView() * zoom; // int pw = xournal->selection->getWidth() * zoom; // int ph = xournal->selection->getHeight() * zoom; // not visible, its on the right side of the visible area if (px > lastVisibleX) { printf("Warning: object on right side of visible area.\n"); } else // not visible, its on the left side of the visible area // TODO LOW PRIO this is not working correct if the zoom is small, xournal->x is never smaller than 0 // if (px + pw < firstVisibleX) { // printf("test2\n"); // } else // not visible, its on the bottom side of the visible area if (py > lastVisibleY) { printf("Warning: object below visible area.\n"); // } else // // not visible, its on the top side of the visible area // if (py + ph < firstVisibleY) { // printf("test4 %i:: %i\n", py + ph, firstVisibleY); } else { Redrawable* red = xournal->selection->getView(); cairo_translate(cr, red->getX() - xournal->x, red->getY() - xournal->y); xournal->selection->paint(cr, zoom); } } cairo_destroy(cr); gdk_threads_leave(); return true; }
void lime_cairo_translate (value handle, double x, double y) { cairo_translate ((cairo_t*)val_data (handle), x, y); }
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); }
static gboolean dt_iop_basecurve_draw(GtkWidget *widget, cairo_t *crf, gpointer user_data) { dt_iop_module_t *self = (dt_iop_module_t *)user_data; dt_iop_basecurve_gui_data_t *c = (dt_iop_basecurve_gui_data_t *)self->gui_data; dt_iop_basecurve_params_t *p = (dt_iop_basecurve_params_t *)self->params; int nodes = p->basecurve_nodes[0]; dt_iop_basecurve_node_t *basecurve = p->basecurve[0]; if(c->minmax_curve_type != p->basecurve_type[0] || c->minmax_curve_nodes != p->basecurve_nodes[0]) { dt_draw_curve_destroy(c->minmax_curve); c->minmax_curve = dt_draw_curve_new(0.0, 1.0, p->basecurve_type[0]); c->minmax_curve_nodes = p->basecurve_nodes[0]; c->minmax_curve_type = p->basecurve_type[0]; for(int k = 0; k < p->basecurve_nodes[0]; k++) (void)dt_draw_curve_add_point(c->minmax_curve, p->basecurve[0][k].x, p->basecurve[0][k].y); } else { for(int k = 0; k < p->basecurve_nodes[0]; k++) dt_draw_curve_set_point(c->minmax_curve, k, p->basecurve[0][k].x, p->basecurve[0][k].y); } dt_draw_curve_t *minmax_curve = c->minmax_curve; dt_draw_curve_calc_values(minmax_curve, 0.0, 1.0, DT_IOP_TONECURVE_RES, c->draw_xs, c->draw_ys); const float xm = basecurve[nodes - 1].x; const float x[4] = { 0.7f * xm, 0.8f * xm, 0.9f * xm, 1.0f * xm }; const float y[4] = { c->draw_ys[CLAMP((int)(x[0] * DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES - 1)], c->draw_ys[CLAMP((int)(x[1] * DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES - 1)], c->draw_ys[CLAMP((int)(x[2] * DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES - 1)], c->draw_ys[CLAMP((int)(x[3] * DT_IOP_TONECURVE_RES), 0, DT_IOP_TONECURVE_RES - 1)] }; float unbounded_coeffs[3]; dt_iop_estimate_exp(x, y, 4, unbounded_coeffs); const int inset = DT_GUI_CURVE_EDITOR_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 bg cairo_set_source_rgb(cr, .2, .2, .2); cairo_paint(cr); cairo_translate(cr, inset, inset); width -= 2 * inset; height -= 2 * inset; #if 0 // draw shadow around float alpha = 1.0f; for(int k=0; k<inset; k++) { cairo_rectangle(cr, -k, -k, width + 2*k, height + 2*k); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.6f; cairo_fill(cr); } #else 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); #endif cairo_set_source_rgb(cr, .3, .3, .3); cairo_rectangle(cr, 0, 0, width, height); cairo_fill(cr); cairo_translate(cr, 0, height); cairo_scale(cr, 1.0f, -1.0f); // draw grid cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(.4)); cairo_set_source_rgb(cr, .1, .1, .1); if(c->loglogscale) dt_draw_loglog_grid(cr, 4, 0, 0, width, height, c->loglogscale); else dt_draw_grid(cr, 4, 0, 0, width, height); // draw nodes positions cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.)); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); for(int k = 0; k < nodes; k++) { const float x = to_log(basecurve[k].x, c->loglogscale), y = to_log(basecurve[k].y, c->loglogscale); cairo_arc(cr, x * width, y * height, DT_PIXEL_APPLY_DPI(3), 0, 2. * M_PI); cairo_stroke(cr); } // draw selected cursor cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.)); if(c->selected >= 0) { cairo_set_source_rgb(cr, .9, .9, .9); const float x = to_log(basecurve[c->selected].x, c->loglogscale), y = to_log(basecurve[c->selected].y, c->loglogscale); cairo_arc(cr, x * width, y * height, DT_PIXEL_APPLY_DPI(4), 0, 2. * M_PI); cairo_stroke(cr); } // draw curve cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.)); cairo_set_source_rgb(cr, .9, .9, .9); // cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE); cairo_move_to(cr, 0, height * to_log(c->draw_ys[0], c->loglogscale)); for(int k = 1; k < DT_IOP_TONECURVE_RES; k++) { const float xx = k / (DT_IOP_TONECURVE_RES - 1.0); if(xx > xm) { const float yy = dt_iop_eval_exp(unbounded_coeffs, xx); const float x = to_log(xx, c->loglogscale), y = to_log(yy, c->loglogscale); cairo_line_to(cr, x * width, height * y); } else { const float yy = c->draw_ys[k]; const float x = to_log(xx, c->loglogscale), y = to_log(yy, c->loglogscale); cairo_line_to(cr, x * width, height * y); } } 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 render (cairo_t *pCairoContext, CairoDesklet *pDesklet) { CDPanelParameters *pPanel = (CDPanelParameters *) pDesklet->pRendererData; //g_print ("%s(%x)\n", __func__, pPanel); if (pPanel == NULL) return ; double fRadius = pPanel->iRadius; double fLineWidth = pPanel->iLineWidth; double fOffsetX = fRadius + fLineWidth/2; double fOffsetY = fLineWidth/2; double fFrameWidth = pDesklet->container.iWidth - 2 * fRadius - fLineWidth; double fFrameHeight = pDesklet->container.iHeight - fLineWidth; // le cadre. cairo_set_line_width (pCairoContext, pPanel->iLineWidth); cairo_move_to (pCairoContext, fOffsetX, fOffsetY); cairo_rel_curve_to (pCairoContext, fFrameWidth/2, 0, fFrameWidth/2, pPanel->iMainIconSize, fFrameWidth, pPanel->iMainIconSize); //\_________________ Coin haut droit. cairo_rel_curve_to (pCairoContext, 0, 0, fRadius, 0, fRadius, fRadius); cairo_rel_line_to (pCairoContext, 0, fFrameHeight - fRadius * 2 - pPanel->iMainIconSize); //\_________________ Coin bas droit. cairo_rel_curve_to (pCairoContext, 0, 0, 0, fRadius, -fRadius, fRadius); cairo_rel_line_to (pCairoContext, - fFrameWidth, 0); //\_________________ Coin bas gauche. cairo_rel_curve_to (pCairoContext, 0, 0, -fRadius, 0, -fRadius, - fRadius); cairo_rel_line_to (pCairoContext, 0, - (fFrameHeight - fRadius * 2)); //\_________________ Coin haut gauche. cairo_rel_curve_to (pCairoContext, 0, 0, 0, -fRadius, fRadius, -fRadius); cairo_set_source_rgba (pCairoContext, pPanel->fBgColor[0], pPanel->fBgColor[1], pPanel->fBgColor[2], 1.); cairo_stroke_preserve (pCairoContext); cairo_set_source_rgba (pCairoContext, pPanel->fBgColor[0], pPanel->fBgColor[1], pPanel->fBgColor[2], pPanel->fBgColor[3]); cairo_fill (pCairoContext); // les icones. Icon *pIcon; GList *ic; pIcon = pDesklet->pIcon; if (pIcon && pIcon->image.pSurface != NULL) { cairo_save (pCairoContext); cairo_translate (pCairoContext, pIcon->fDrawX, pIcon->fDrawY); cairo_dock_apply_image_buffer_surface_with_offset (&pIcon->image, pCairoContext, 0, 0, pIcon->fAlpha); cairo_dock_draw_icon_overlays_cairo (pIcon, pDesklet->container.fRatio, pCairoContext); cairo_restore (pCairoContext); } GList *pFirstDrawnElement = cairo_dock_get_first_drawn_element_linear (pDesklet->icons); if (pFirstDrawnElement == NULL) return; ic = pFirstDrawnElement; do { pIcon = ic->data; if (pIcon->image.pSurface != NULL && ! CAIRO_DOCK_ICON_TYPE_IS_SEPARATOR (pIcon)) { cairo_save (pCairoContext); cairo_translate (pCairoContext, pIcon->fDrawX, pIcon->fDrawY); cairo_dock_apply_image_buffer_surface_with_offset (&pIcon->image, pCairoContext, 0, 0, pIcon->fAlpha); if (pIcon->label.pSurface != NULL) { cairo_save (pCairoContext); double fOffsetX = 0., fAlpha; if (pIcon->bPointed) { fAlpha = 1.; /**if (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->label.iWidth/2 > pDesklet->container.iWidth) fOffsetX = pDesklet->container.iWidth - (pIcon->fDrawX + pIcon->fWidth/2 + pIcon->label.iWidth/2); if (pIcon->fDrawX + pIcon->fWidth/2 - pIcon->label.iWidth/2 < 0) fOffsetX = pIcon->label.iWidth/2 - (pIcon->fDrawX + pIcon->fWidth/2); cairo_set_source_surface (pCairoContext, pIcon->label.pSurface, fOffsetX + pIcon->fWidth/2 - pIcon->label.iWidth/2, -myIconsParam.iLabelSize);*/ cairo_set_source_surface (pCairoContext, pIcon->label.pSurface, 0., -myIconsParam.iLabelSize); cairo_paint_with_alpha (pCairoContext, fAlpha); } else { fAlpha = .6; if (pIcon->label.iWidth > 2*pIcon->fWidth + 0 * myIconsParam.iLabelSize) { ///fOffsetX = - myIconsParam.iLabelSize; cairo_pattern_t *pGradationPattern = cairo_pattern_create_linear (fOffsetX, 0., fOffsetX + 2*pIcon->fWidth + 0*myIconsParam.iLabelSize, 0.); cairo_pattern_set_extend (pGradationPattern, CAIRO_EXTEND_NONE); cairo_pattern_add_color_stop_rgba (pGradationPattern, 0., 0., 0., 0., fAlpha); cairo_pattern_add_color_stop_rgba (pGradationPattern, 0.75, 0., 0., 0., fAlpha); cairo_pattern_add_color_stop_rgba (pGradationPattern, 1., 0., 0., 0., 0.); cairo_set_source_surface (pCairoContext, pIcon->label.pSurface, fOffsetX, -myIconsParam.iLabelSize); cairo_mask (pCairoContext, pGradationPattern); cairo_pattern_destroy (pGradationPattern); } else { ///fOffsetX = pIcon->fWidth/2 - pIcon->label.iWidth/2; cairo_set_source_surface (pCairoContext, pIcon->label.pSurface, fOffsetX, -myIconsParam.iLabelSize); cairo_paint_with_alpha (pCairoContext, fAlpha); } } cairo_restore (pCairoContext); } cairo_translate (pCairoContext, pIcon->fWidth, - pIcon->fHeight/2); // not ideal, it should be vertically centered. cairo_dock_draw_icon_overlays_cairo (pIcon, pDesklet->container.fRatio, pCairoContext); cairo_restore (pCairoContext); } ic = cairo_dock_get_next_element (ic, pDesklet->icons); } while (ic != pFirstDrawnElement); }
static cairo_test_status_t draw (cairo_t *cr, int width, int height) { const double dash[2] = {.5, .5}; cairo_set_source_rgb (cr, 1, 1, 1); cairo_paint (cr); cairo_set_source_rgb (cr, 1., 0., 0); /* By adjusting the miter limit, we can see variations on the artifact. * cairo_set_miter_limit (cr, 4.); */ cairo_translate (cr, -720, -484); cairo_scale (cr, 2.5, 2.5); cairo_set_dash (cr, dash, 2, 0); cairo_move_to (cr, 293.622, 330); cairo_line_to (cr, 293.703, 337.028); cairo_line_to (cr, 297.45, 336.851); cairo_line_to (cr, 308.88, 342.609); cairo_line_to (cr, 309.736, 346.107); cairo_line_to (cr, 312.972, 348.128); cairo_line_to (cr, 312.977, 353.478); cairo_line_to (cr, 322.486, 359.355); cairo_line_to (cr, 320.831, 363.642); cairo_line_to (cr, 315.175, 367.171); cairo_line_to (cr, 308.987, 365.715); cairo_line_to (cr, 301.3, 365.964); cairo_line_to (cr, 304.712, 368.852); cairo_line_to (cr, 305.349, 373.022); cairo_line_to (cr, 303.211, 376.551); cairo_line_to (cr, 304.915, 382.855); cairo_line_to (cr, 323.715, 400.475); cairo_line_to (cr, 355.323, 424.072); cairo_line_to (cr, 443.078, 426.534); cairo_line_to (cr, 455.26, 400.603); cairo_line_to (cr, 471.924, 392.604); cairo_line_to (cr, 478.556, 390.797); cairo_line_to (cr, 477.715, 386); cairo_line_to (cr, 456.807, 376.507); cairo_line_to (cr, 449.134, 368.722); cairo_line_to (cr, 449.147, 365.847); cairo_line_to (cr, 439.981, 361.692); cairo_line_to (cr, 439.994, 358.603); cairo_line_to (cr, 454.645, 336.128); cairo_line_to (cr, 434.995, 324.005); cairo_line_to (cr, 423.884, 319.354); cairo_line_to (cr, 421.098, 312.569); cairo_line_to (cr, 424.291, 305.997); cairo_line_to (cr, 431.308, 305.069); cairo_line_to (cr, 437.257, 296.882); cairo_line_to (cr, 448.544, 296.808); cairo_line_to (cr, 452.113, 290.651); cairo_line_to (cr, 448.469, 285.483); cairo_line_to (cr, 442.903, 282.877); cairo_line_to (cr, 447.798, 281.124); cairo_line_to (cr, 454.622, 274.911); cairo_line_to (cr, 449.491, 269.978); cairo_line_to (cr, 443.666, 253.148); cairo_line_to (cr, 445.741, 250.834); cairo_line_to (cr, 441.87, 247.131); cairo_line_to (cr, 436.932, 246.203); cairo_line_to (cr, 430.5, 251.252); cairo_line_to (cr, 427.483, 250.751); cairo_line_to (cr, 427.26, 253.572); cairo_line_to (cr, 423.621, 255.539); cairo_line_to (cr, 423.824, 257.933); cairo_line_to (cr, 425.239, 259.582); cairo_line_to (cr, 422.385, 261.443); cairo_line_to (cr, 421.665, 260.53); cairo_line_to (cr, 419.238, 262.819); cairo_line_to (cr, 418.731, 257.849); cairo_line_to (cr, 419.72, 255.227); cairo_line_to (cr, 418.786, 250.258); cairo_line_to (cr, 405.685, 235.254); cairo_line_to (cr, 427.167, 215.127); cairo_line_to (cr, 413.852, 196.281); cairo_line_to (cr, 420.177, 192.379); cairo_line_to (cr, 419.885, 185.701); cairo_line_to (cr, 413.401, 185.428); cairo_line_to (cr, 407.985, 186.863); cairo_line_to (cr, 397.11, 189.112); cairo_line_to (cr, 390.505, 186.664); cairo_line_to (cr, 388.527, 183.694); cairo_line_to (cr, 336.503, 221.048); cairo_line_to (cr, 367.028, 241.656); cairo_line_to (cr, 365.103, 244.117); cairo_line_to (cr, 364.886, 246.792); cairo_line_to (cr, 361.467, 247.119); cairo_line_to (cr, 360.396, 245.525); cairo_line_to (cr, 356.336, 245.638); cairo_line_to (cr, 353.344, 242.122); cairo_line_to (cr, 347.149, 242.876); cairo_line_to (cr, 341.809, 256.652); cairo_line_to (cr, 342.232, 268.72); cairo_line_to (cr, 329.579, 269.095); cairo_line_to (cr, 327.001, 271.009); cairo_line_to (cr, 325.579, 275.598); cairo_line_to (cr, 318.941, 277.313); cairo_line_to (cr, 306.048, 277.231); cairo_line_to (cr, 304.071, 276.27); cairo_line_to (cr, 301.153, 277.175); cairo_line_to (cr, 293.52, 277.529); cairo_line_to (cr, 290.682, 281.947); cairo_line_to (cr, 293.911, 286.63); cairo_line_to (cr, 302.417, 290.547); cairo_line_to (cr, 303.521, 294.73); cairo_line_to (cr, 307.787, 298.088); cairo_line_to (cr, 311.718, 299.126); cairo_line_to (cr, 313.255, 302.146); cairo_line_to (cr, 314.6, 306.206); cairo_line_to (cr, 322.603, 308.96); cairo_line_to (cr, 321.718, 314.477); cairo_line_to (cr, 319.596, 320.341); cairo_line_to (cr, 300.689, 323.69); cairo_line_to (cr, 301.232, 326.789); cairo_line_to (cr, 293.622, 330); cairo_close_path (cr); cairo_stroke (cr); return CAIRO_TEST_SUCCESS; }
static void _view_map_post_expose(cairo_t *cri, int32_t width_i, int32_t height_i, int32_t pointerx, int32_t pointery, gpointer user_data) { const int ts = 64; OsmGpsMapPoint bb[2], *l=NULL, *center=NULL; int px,py; dt_map_t *lib = (dt_map_t *)user_data; /* get bounding box coords */ osm_gps_map_get_bbox(lib->map, &bb[0], &bb[1]); float bb_0_lat = 0.0, bb_0_lon = 0.0, bb_1_lat = 0.0, bb_1_lon = 0.0; osm_gps_map_point_get_degrees(&bb[0], &bb_0_lat, &bb_0_lon); osm_gps_map_point_get_degrees(&bb[1], &bb_1_lat, &bb_1_lon); /* make the bounding box a little bigger to the west and south */ float lat0 = 0.0, lon0 = 0.0, lat1 = 0.0, lon1 = 0.0; OsmGpsMapPoint *pt0 = osm_gps_map_point_new_degrees(0.0, 0.0), *pt1 = osm_gps_map_point_new_degrees(0.0, 0.0); osm_gps_map_convert_screen_to_geographic(lib->map, 0, 0, pt0); osm_gps_map_convert_screen_to_geographic(lib->map, 1.5*ts, 1.5*ts, pt1); osm_gps_map_point_get_degrees(pt0, &lat0, &lon0); osm_gps_map_point_get_degrees(pt1, &lat1, &lon1); osm_gps_map_point_free(pt0); osm_gps_map_point_free(pt1); double south_border = lat0 - lat1, west_border = lon1 - lon0; /* get map view state and store */ int zoom = osm_gps_map_get_zoom(lib->map); center = osm_gps_map_get_center(lib->map); dt_conf_set_float("plugins/map/longitude", center->rlon); dt_conf_set_float("plugins/map/latitude", center->rlat); dt_conf_set_int("plugins/map/zoom", zoom); osm_gps_map_point_free(center); /* let's reset and reuse the main_query statement */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); /* bind bounding box coords for the main query */ DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 1, bb_0_lon - west_border); DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 2, bb_1_lon); DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 3, bb_0_lat); DT_DEBUG_SQLITE3_BIND_DOUBLE(lib->statements.main_query, 4, bb_1_lat - south_border); /* query collection ids */ while(sqlite3_step(lib->statements.main_query) == SQLITE_ROW) { int32_t imgid = sqlite3_column_int(lib->statements.main_query, 0); cairo_set_source_rgba(cri, 0, 0, 0, 0.4); /* free l if allocated */ if (l) osm_gps_map_point_free(l); /* for each image check if within bbox */ const dt_image_t *cimg = dt_image_cache_read_get(darktable.image_cache, imgid); double longitude = cimg->longitude; double latitude = cimg->latitude; dt_image_cache_read_release(darktable.image_cache, cimg); if(isnan(latitude) || isnan(longitude)) continue; l = osm_gps_map_point_new_degrees(latitude, longitude); /* translate l into screen coords */ osm_gps_map_convert_geographic_to_screen(lib->map, l, &px, &py); /* dependent on scale draw different overlays */ if (zoom >= 14) { dt_mipmap_buffer_t buf; dt_mipmap_size_t mip = dt_mipmap_cache_get_matching_size(darktable.mipmap_cache, ts, ts); dt_mipmap_cache_read_get(darktable.mipmap_cache, &buf, imgid, mip, 0); cairo_surface_t *surface = NULL; if(buf.buf) { float ms = fminf( ts/(float)buf.width, ts/(float)buf.height); #if 0 // this doesn't work since osm-gps-map always gives 0/0 as mouse coords :( /* find out if the cursor is over the image */ if(pointerx >= px && pointerx <= (px + buf.width*ms + 4) && pointery <= (py - 8) && pointery >= (py - buf.height*ms - 8 - 4)) { printf("over\n"); cairo_set_source_rgba(cri, 1, 0, 0, 0.7); } // else // printf("%d/%d, %d/%d\n", px, py, pointerx, pointery); #endif const int32_t stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, buf.width); surface = cairo_image_surface_create_for_data (buf.buf, CAIRO_FORMAT_RGB24, buf.width, buf.height, stride); cairo_pattern_set_filter(cairo_get_source(cri), CAIRO_FILTER_NEAREST); cairo_save(cri); /* first of lets draw a pin */ cairo_move_to(cri, px, py); cairo_line_to(cri, px+8, py-8); cairo_line_to(cri, px+4, py-8); cairo_fill(cri); /* and the frame around image */ cairo_move_to(cri, px+2, py-8); cairo_line_to(cri, px+2 + (buf.width*ms) + 4, py-8); cairo_line_to(cri, px+2 + (buf.width*ms) + 4 , py-8-(buf.height*ms) - 4); cairo_line_to(cri, px+2 , py-8-(buf.height*ms) - 4); cairo_fill(cri); /* draw image*/ cairo_translate(cri, px+4, py - 8 - (buf.height*ms) - 2); cairo_scale(cri, ms, ms); cairo_set_source_surface (cri, surface, 0, 0); cairo_paint(cri); cairo_restore(cri); cairo_surface_destroy(surface); } } else { /* just draw a patch indicating that there is images at the location */ cairo_rectangle(cri, px-8, py-8, 16, 16); cairo_fill(cri); } } }
static void expose_zoomable (dt_view_t *self, cairo_t *cr, int32_t width, int32_t height, int32_t pointerx, int32_t pointery) { dt_library_t *lib = (dt_library_t *)self->data; float zoom, zoom_x, zoom_y; int32_t mouse_over_id, pan, track, center; /* query new collection count */ lib->collection_count = dt_collection_get_count (darktable.collection); DT_CTL_GET_GLOBAL(mouse_over_id, lib_image_mouse_over_id); zoom = dt_conf_get_int("plugins/lighttable/images_in_row"); zoom_x = lib->zoom_x; zoom_y = lib->zoom_y; pan = lib->pan; center = lib->center; track = lib->track; lib->image_over = DT_VIEW_DESERT; cairo_set_source_rgb (cr, .2, .2, .2); cairo_paint(cr); const float wd = width/zoom; const float ht = width/zoom; static int oldpan = 0; static float oldzoom = -1; if(oldzoom < 0) oldzoom = zoom; // TODO: exaggerate mouse gestures to pan when zoom == 1 if(pan)// && mouse_over_id >= 0) { zoom_x = lib->select_offset_x - /* (zoom == 1 ? 2. : 1.)*/pointerx; zoom_y = lib->select_offset_y - /* (zoom == 1 ? 2. : 1.)*/pointery; } if(!lib->statements.main_query) return; if (track == 0); else if(track > 1) zoom_y += ht; else if(track > 0) zoom_x += wd; else if(track > -2) zoom_x -= wd; else zoom_y -= ht; if(zoom > DT_LIBRARY_MAX_ZOOM) { // double speed. if (track == 0); else if(track > 1) zoom_y += ht; else if(track > 0) zoom_x += wd; else if(track > -2) zoom_x -= wd; else zoom_y -= ht; if(zoom > 1.5*DT_LIBRARY_MAX_ZOOM) { // quad speed. if (track == 0); else if(track > 1) zoom_y += ht; else if(track > 0) zoom_x += wd; else if(track > -2) zoom_x -= wd; else zoom_y -= ht; } } if(oldzoom != zoom) { float oldx = (pointerx + zoom_x)*oldzoom/width; float oldy = (pointery + zoom_y)*oldzoom/width; if(zoom == 1) { zoom_x = (int)oldx*wd; zoom_y = (int)oldy*ht; lib->offset = 0x7fffffff; } else { zoom_x = oldx*wd - pointerx; zoom_y = oldy*ht - pointery; } } oldzoom = zoom; // TODO: replace this with center on top of selected/developed image if(center) { if(mouse_over_id >= 0) { zoom_x = wd*((int)(zoom_x)/(int)wd); zoom_y = ht*((int)(zoom_y)/(int)ht); } else zoom_x = zoom_y = 0.0; center = 0; } // mouse left the area, but we leave mouse over as it was, especially during panning // if(!pan && pointerx > 0 && pointerx < width && pointery > 0 && pointery < height) DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1); if(!pan && zoom != 1) DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, -1); // set scrollbar positions, clamp zoom positions if(lib->collection_count == 0) { zoom_x = zoom_y = 0.0f; } else if(zoom < 1.01) { if(zoom_x < 0) zoom_x = 0; if(zoom_x > wd*DT_LIBRARY_MAX_ZOOM-wd) zoom_x = wd*DT_LIBRARY_MAX_ZOOM-wd; if(zoom_y < 0) zoom_y = 0; if(zoom_y > ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht) zoom_y = ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht; } else { if(zoom_x < -wd*DT_LIBRARY_MAX_ZOOM/2) zoom_x = -wd*DT_LIBRARY_MAX_ZOOM/2; if(zoom_x > wd*DT_LIBRARY_MAX_ZOOM-wd) zoom_x = wd*DT_LIBRARY_MAX_ZOOM-wd; if(zoom_y < -height+ht) zoom_y = -height+ht; if(zoom_y > ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht) zoom_y = ht*lib->collection_count/MIN(DT_LIBRARY_MAX_ZOOM, zoom)-ht; } int offset_i = (int)(zoom_x/wd); int offset_j = (int)(zoom_y/ht); if(lib->first_visible_filemanager >= 0) { offset_i = lib->first_visible_filemanager % DT_LIBRARY_MAX_ZOOM; offset_j = lib->first_visible_filemanager / DT_LIBRARY_MAX_ZOOM; } lib->first_visible_filemanager = -1; lib->first_visible_zoomable = offset_i + DT_LIBRARY_MAX_ZOOM*offset_j; // arbitrary 1000 to avoid bug due to round towards zero using (int) int seli = zoom == 1 ? 0 : ((int)(1000 + (pointerx + zoom_x)/wd) - MAX(offset_i, 0) - 1000); int selj = zoom == 1 ? 0 : ((int)(1000 + (pointery + zoom_y)/ht) - offset_j - 1000); float offset_x = (zoom == 1) ? 0.0 : (zoom_x/wd - (int)(zoom_x/wd)); float offset_y = (zoom == 1) ? 0.0 : (zoom_y/ht - (int)(zoom_y/ht)); const int max_rows = (zoom == 1) ? 1 : (2 + (int)((height)/ht + .5)); const int max_cols = (zoom == 1) ? 1 : (MIN(DT_LIBRARY_MAX_ZOOM - MAX(0, offset_i), 1 + (int)(zoom+.5))); int offset = MAX(0, offset_i) + DT_LIBRARY_MAX_ZOOM*offset_j; int img_pointerx = zoom == 1 ? pointerx : fmodf(pointerx + zoom_x, wd); int img_pointery = zoom == 1 ? pointery : fmodf(pointery + zoom_y, ht); // assure 1:1 is not switching images on resize/tab events: if(!track && lib->offset != 0x7fffffff && zoom == 1) { offset = lib->offset; zoom_x = wd*(offset % DT_LIBRARY_MAX_ZOOM); zoom_y = ht*(offset / DT_LIBRARY_MAX_ZOOM); } else lib->offset = offset; int id, clicked1, last_seli = 1<<30, last_selj = 1<<30; clicked1 = (oldpan == 0 && pan == 1 && lib->button == 1); dt_view_set_scrollbar(self, MAX(0, offset_i), DT_LIBRARY_MAX_ZOOM, zoom, DT_LIBRARY_MAX_ZOOM*offset_j, lib->collection_count, DT_LIBRARY_MAX_ZOOM*max_cols); cairo_translate(cr, -offset_x*wd, -offset_y*ht); cairo_translate(cr, -MIN(offset_i*wd, 0.0), 0.0); for(int row = 0; row < max_rows; row++) { if(offset < 0) { cairo_translate(cr, 0, ht); offset += DT_LIBRARY_MAX_ZOOM; continue; } /* clear and reset main query */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.main_query); DT_DEBUG_SQLITE3_RESET(lib->statements.main_query); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 1, offset); DT_DEBUG_SQLITE3_BIND_INT(lib->statements.main_query, 2, max_cols); for(int col = 0; col < max_cols; col++) { if(sqlite3_step(lib->statements.main_query) == SQLITE_ROW) { id = sqlite3_column_int(lib->statements.main_query, 0); // set mouse over id if((zoom == 1 && mouse_over_id < 0) || ((!pan || track) && seli == col && selj == row)) { mouse_over_id = id; DT_CTL_SET_GLOBAL(lib_image_mouse_over_id, mouse_over_id); } // add clicked image to selected table if(clicked1) { if((lib->modifiers & GDK_SHIFT_MASK) == 0 && (lib->modifiers & GDK_CONTROL_MASK) == 0 && seli == col && selj == row) { /* clear selection except id */ /* clear and resest statement */ DT_DEBUG_SQLITE3_CLEAR_BINDINGS(lib->statements.delete_except_arg); DT_DEBUG_SQLITE3_RESET(lib->statements.delete_except_arg); /* reuse statment */ DT_DEBUG_SQLITE3_BIND_INT(lib->statements.delete_except_arg, 1, id); sqlite3_step(lib->statements.delete_except_arg); } // FIXME: whatever comes first assumtion is broken! // if((lib->modifiers & GDK_SHIFT_MASK) && (last_seli == (1<<30)) && // (image->id == lib->last_selected_id || image->id == mouse_over_id)) { last_seli = col; last_selj = row; } // if(last_seli < (1<<30) && ((lib->modifiers & GDK_SHIFT_MASK) && (col >= MIN(last_seli,seli) && row >= MIN(last_selj,selj) && // col <= MAX(last_seli,seli) && row <= MAX(last_selj,selj)) && (col != last_seli || row != last_selj)) || if((lib->modifiers & GDK_SHIFT_MASK) && id == lib->last_selected_idx) { last_seli = col; last_selj = row; } if((last_seli < (1<<30) && ((lib->modifiers & GDK_SHIFT_MASK) && (col >= last_seli && row >= last_selj && col <= seli && row <= selj) && (col != last_seli || row != last_selj))) || (seli == col && selj == row)) { // insert all in range if shift, or only the one the mouse is over for ctrl or plain click. dt_view_toggle_selection(id); lib->last_selected_idx = id; } } cairo_save(cr); // if(zoom == 1) dt_image_prefetch(image, DT_IMAGE_MIPF); dt_view_image_expose(&(lib->image_over), id, cr, wd, zoom == 1 ? height : ht, zoom, img_pointerx, img_pointery); cairo_restore(cr); } else goto failure; cairo_translate(cr, wd, 0.0f); } cairo_translate(cr, -max_cols*wd, ht); offset += DT_LIBRARY_MAX_ZOOM; } failure: oldpan = pan; lib->zoom_x = zoom_x; lib->zoom_y = zoom_y; lib->track = 0; lib->center = center; if(darktable.unmuted & DT_DEBUG_CACHE) dt_mipmap_cache_print(darktable.mipmap_cache); }
void render_hex (cairo_t *cr, int x, int y, int w) { cairo_pattern_t *pat; static float hexrot = 0; int r1; float scale; cairo_save(cr); cairo_set_line_width(cr, 1); cairo_set_source_rgb(cr, ORANGE); scale = 2.5; r1 = ((w)/2 * sqrt(3)); cairo_translate (cr, x, y); cairo_rotate (cr, hexrot * (M_PI/180.0)); cairo_translate (cr, -(w/2), -r1); cairo_move_to (cr, 0, 0); cairo_rel_line_to (cr, w, 0); cairo_rotate (cr, 60 * (M_PI/180.0)); cairo_rel_line_to (cr, w, 0); cairo_rotate (cr, 60 * (M_PI/180.0)); cairo_rel_line_to (cr, w, 0); cairo_rotate (cr, 60 * (M_PI/180.0)); cairo_rel_line_to (cr, w, 0); cairo_rotate (cr, 60 * (M_PI/180.0)); cairo_rel_line_to (cr, w, 0); cairo_rotate (cr, 60 * (M_PI/180.0)); cairo_rel_line_to (cr, w, 0); hexrot += 1.5; cairo_fill (cr); cairo_restore(cr); cairo_save(cr); cairo_set_line_width(cr, 1.5); cairo_set_operator(cr, CAIRO_OPERATOR_ADD); cairo_set_source_rgb(cr, GREY); cairo_translate (cr, x, y); cairo_rotate (cr, hexrot * (M_PI/180.0)); cairo_translate (cr, -((w * scale)/2), -r1 * scale); cairo_scale(cr, scale, scale); cairo_move_to (cr, 0, 0); cairo_rel_line_to (cr, w, 0); cairo_rotate (cr, 60 * (M_PI/180.0)); cairo_rel_line_to (cr, w, 0); cairo_rotate (cr, 60 * (M_PI/180.0)); cairo_rel_line_to (cr, w, 0); cairo_rotate (cr, 60 * (M_PI/180.0)); cairo_rel_line_to (cr, w, 0); cairo_rotate (cr, 60 * (M_PI/180.0)); cairo_rel_line_to (cr, w, 0); cairo_rotate (cr, 60 * (M_PI/180.0)); cairo_rel_line_to (cr, w, 0); cairo_rotate (cr, 60 * (M_PI/180.0)); cairo_set_operator(cr, CAIRO_OPERATOR_ADD); pat = cairo_pattern_create_radial (w/2, r1, 3, w/2, r1, r1*scale); cairo_pattern_add_color_stop_rgba (pat, 0, 0, 0, 1, 1); cairo_pattern_add_color_stop_rgba (pat, 0.4, 0, 0, 0, 0); cairo_set_source (cr, pat); cairo_fill (cr); cairo_pattern_destroy (pat); cairo_restore(cr); }