/* * render functions */ static void begin_render(DiaRenderer *self, const Rectangle *update) { DiaCairoRenderer *renderer = DIA_CAIRO_RENDERER (self); real onedu = 0.0; real lmargin = 0.0, tmargin = 0.0; gboolean paginated = renderer->surface && /* only with our own pagination, not GtkPrint */ cairo_surface_get_type (renderer->surface) == CAIRO_SURFACE_TYPE_PDF && !renderer->skip_show_page; if (renderer->surface && !renderer->cr) renderer->cr = cairo_create (renderer->surface); else g_assert (renderer->cr); /* remember current state, so we can start from new with every page */ cairo_save (renderer->cr); if (paginated && renderer->dia) { DiagramData *data = renderer->dia; /* Dia's paper.width already contains the scale, cairo needs it without * Similar for margins, Dia's without, but cairo wants them? */ real width = (data->paper.lmargin + data->paper.width * data->paper.scaling + data->paper.rmargin) * (72.0 / 2.54) + 0.5; real height = (data->paper.tmargin + data->paper.height * data->paper.scaling + data->paper.bmargin) * (72.0 / 2.54) + 0.5; /* "Changes the size of a PDF surface for the current (and * subsequent) pages." Pagination setup? */ cairo_pdf_surface_set_size (renderer->surface, width, height); lmargin = data->paper.lmargin / data->paper.scaling; tmargin = data->paper.tmargin / data->paper.scaling; } cairo_scale (renderer->cr, renderer->scale, renderer->scale); /* to ensure no clipping at top/left we need some extra gymnastics, * otherwise a box with a line witdh one one pixel might loose the * top/left border as in bug #147386 */ ensure_minimum_one_device_unit (renderer, &onedu); if (update && paginated) { cairo_rectangle (renderer->cr, lmargin, tmargin, update->right - update->left, update->bottom - update->top); cairo_clip (renderer->cr); cairo_translate (renderer->cr, -update->left + lmargin, -update->top + tmargin); } else cairo_translate (renderer->cr, -renderer->dia->extents.left + onedu, -renderer->dia->extents.top + onedu); /* no more blurred UML diagrams */ cairo_set_antialias (renderer->cr, CAIRO_ANTIALIAS_NONE); /* clear background */ if (renderer->with_alpha) { cairo_set_operator (renderer->cr, CAIRO_OPERATOR_SOURCE); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 0.0); } else { cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } cairo_paint (renderer->cr); if (renderer->with_alpha) { /* restore to default drawing */ cairo_set_operator (renderer->cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (renderer->cr, renderer->dia->bg_color.red, renderer->dia->bg_color.green, renderer->dia->bg_color.blue, 1.0); } #ifdef HAVE_PANGOCAIRO_H if (!renderer->layout) renderer->layout = pango_cairo_create_layout (renderer->cr); #endif cairo_set_fill_rule (renderer->cr, CAIRO_FILL_RULE_EVEN_ODD); #if 0 /* try to work around bug #341481 - no luck */ { cairo_font_options_t *fo = cairo_font_options_create (); cairo_get_font_options (renderer->cr, fo); /* try to switch off kerning */ cairo_font_options_set_hint_style (fo, CAIRO_HINT_STYLE_NONE); cairo_font_options_set_hint_metrics (fo, CAIRO_HINT_METRICS_OFF); cairo_set_font_options (renderer->cr, fo); cairo_font_options_destroy (fo); #ifdef HAVE_PANGOCAIRO_H pango_cairo_update_context (renderer->cr, pango_layout_get_context (renderer->layout)); pango_layout_context_changed (renderer->layout); #endif } #endif DIAG_STATE(renderer->cr) }
gboolean ly_3lrc_desktop_on_expose_cb (GtkWidget * widget, cairo_t *cr, gpointer data) { gchar desktop_font[1024]="Sans Regular 25"; ly_reg_get("3lrc_desktop_font", "%1024[^\n]", desktop_font); gchar path[1024]; g_snprintf(path,sizeof(path),"%sicon/null.png",LY_GLB_PROG_UIXDIR); if(!desktop_bg) desktop_bg=cairo_image_surface_create_from_png(path); cairo_set_source_surface(cr, desktop_bg, 0, 0); cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); cairo_paint(cr); int width; int height; width = gtk_widget_get_allocated_width (widget); height = gtk_widget_get_allocated_height (widget); int x=0; int y=height; //鼠标进入 if(flag_notify) { //填充圆角矩形拖动区域 cairo_set_source_rgba(cr,0,0,0,0.3); cairo_move_to (cr, 0 + 5, 0); cairo_line_to (cr, 0 + width - 5, 0); cairo_move_to (cr, 0 + width, 0 + 5); cairo_line_to (cr, 0 + width, 0 + height - 5); cairo_move_to (cr, 0 + width - 5, 0 + height); cairo_line_to (cr, 0 + 5, 0 + height); cairo_move_to (cr, 0, 0 + height - 5); cairo_line_to (cr, 0, 0 + 5); cairo_arc (cr, 0 + 5, 0 + 5, 5, M_PI, 3 * M_PI / 2.0); cairo_arc (cr, 0 + width - 5, 0 + 5, 5, 3 * M_PI / 2, 2 * M_PI); cairo_arc (cr, 0 + width - 5, 0 + height - 5, 5, 0, M_PI / 2); cairo_arc (cr, 0 + 5, 0 + height - 5, 5, M_PI / 2, M_PI); cairo_fill(cr); } if(ly_lrc_get_length()>0) { //计算占空比 gint64 t1=0; gint64 t2=0; LyMdhMetadata *md=NULL; md=ly_pqm_get_current_md(); if(!md) return FALSE; if(ly_lrc_get_index()+1<ly_lrc_get_length()) t1=(ly_lrc_get_array()[ly_lrc_get_index()+1])->time-(ly_lrc_get_array()[ly_lrc_get_index()])->time; else t1=ly_mdh_time_str2int(md->duration)-ly_mdh_time_str2int(md->start)-(ly_lrc_get_array()[ly_lrc_get_index()])->time; t2=ly_aud_get_position_abs()-ly_mdh_time_str2int(md->start)-(ly_lrc_get_array()[ly_lrc_get_index()])->time; if(t1!=0) { x=(int)((t2/(gdouble)t1)*pos_layout[X]); } //画歌词 cairo_set_source_rgb(cr,0,0,0); //确定起始点 if((x>=width/2)&&(pos_layout[X]>width)&&(width<(pos_layout[X]-x)*2)) { cairo_move_to(cr, 0-(x-width/2), 5); x=width/2; } else if((x>=width/2)&&(pos_layout[X]>width)&&(width>=(pos_layout[X]-x)*2)) cairo_move_to(cr, 0-(pos_layout[X]-width), 5); else cairo_move_to(cr, 0, 5); PangoLayout *layout; PangoFontDescription *desc; layout = pango_cairo_create_layout (cr); pango_layout_set_text(layout, ly_lrc_get_array()[ly_lrc_get_index()]->text, -1); desc = pango_font_description_from_string (desktop_font); pango_layout_set_font_description (layout, desc); pango_font_description_free (desc); pango_layout_get_size(layout,&pos_layout[X],&pos_layout[Y]); pos_layout[X]=pos_layout[X]/1000; pango_cairo_update_layout (cr, layout); pango_cairo_layout_path (cr, layout); cairo_clip(cr); g_object_unref (layout); //画背景条 cairo_pattern_t *pat; pat = cairo_pattern_create_linear (0, 0,10.0, 150); cairo_pattern_add_color_stop_rgb (pat, 0.1, 65535/65535.0, 10449/65535.0, 0/65535.0); cairo_pattern_add_color_stop_rgb (pat, 0.5, 65535/65535.0, 61062/65535.0, 0/65535.0); cairo_pattern_add_color_stop_rgb (pat, 0.9, 65535/65535.0, 10449/65535.0, 0/65535.0); //画矩形 if((x>=width/2)&&(pos_layout[X]>width)&&(width<(pos_layout[X]-x)*2)) cairo_rectangle (cr, 0, 0, width/2, y); else if((x>=width/2)&&(pos_layout[X]>width)&&(width>=(pos_layout[X]-x)*2)) cairo_rectangle (cr, 0, 0, width-(pos_layout[X]-x), y); else cairo_rectangle (cr, 0, 0, x, y); cairo_set_source (cr, pat); cairo_fill(cr); cairo_pattern_destroy (pat); pat = cairo_pattern_create_linear (0, 0,10.0, 150); cairo_pattern_add_color_stop_rgb (pat, 0.1, 19532/65535.0, 65535/65535.0, 65535/65535.0); cairo_pattern_add_color_stop_rgb (pat, 0.5, 5539/65535.0, 0/65535.0, 65535/65535.0); cairo_pattern_add_color_stop_rgb (pat, 0.9, 19532/65535.0, 65535/65535.0, 65535/65535.0); //画矩形 if((x>=width/2)&&(pos_layout[X]>width)&&(width<(pos_layout[X]-x)*2)) cairo_rectangle (cr, width/2, 0, width-(width/2), y); else if((x>=width/2)&&(pos_layout[X]>width)&&(width>=(pos_layout[X]-x)*2)) cairo_rectangle (cr, width-(pos_layout[X]-x), 0, pos_layout[X]-x, y); else cairo_rectangle (cr, x, 0, width-x, y); cairo_set_source (cr, pat); cairo_fill(cr); cairo_pattern_destroy (pat); } int lrc_desktop=1; int lrc_desktop_fix=0; if(!ly_reg_get("3lrc_desktop_state", "%d:%d", &lrc_desktop, &lrc_desktop_fix)) { ly_reg_set("3lrc_desktop_state", "%d:%d", lrc_desktop, lrc_desktop_fix); } if(lrc_desktop_fix>0) gtk_widget_set_sensitive(widget,FALSE); else gtk_widget_set_sensitive(widget,TRUE); cairo_region_t *region; if(!(lrc_desktop_fix)) { cairo_rectangle_int_t rect; rect.x=rect.y=0; rect.width=width; rect.height=height; region=cairo_region_create_rectangle(&rect); } else { region=cairo_region_create(); } gdk_window_input_shape_combine_region (gtk_widget_get_window(widget), region, 0, 0); cairo_region_destroy (region); return FALSE; }
void hb_export_pdf_listview(GtkTreeView *treeview, gchar *filepath, gchar *accname) { cairo_surface_t *surf; cairo_t *cr; PdfPrintContext ppc; PangoFontDescription *desc; PangoLayout *layout; GtkTreeModel *model; GtkTreeIter iter; gboolean valid; gint i, col; DB( g_print("[gtk-chart] export to pdf\n") ); model = gtk_tree_view_get_model(treeview); papersize(&ppc); //gchar *filename = "/home/max/Desktop/hb-txn-export.pdf"; double width; //=210 * 2.83; double height; //=297 * 2.83; width = ppc.w; height = ppc.h; surf = cairo_pdf_surface_create (filepath, width, height); if( cairo_surface_status(surf) != CAIRO_STATUS_SUCCESS ) //todo: manage error later on return; cr = cairo_create (surf); //cairo_pdf_surface_set_size(surf, width * 2.83, height * 2.83); //g_print("width=%d\n", cairo_image_surface_get_width( surf)); double x1, x2, y1, y2; cairo_clip_extents (cr, &x1, &y1, &x2, &y2); DB( g_print("surface w=%f, h=%f\n", x2 - x1, y2 - y1) ); double pwidth = x2 - x1; /* Create a PangoLayout, set the font and text */ layout = pango_cairo_create_layout (cr); /* get and copy the font from the treeview widget */ gtk_style_context_get(gtk_widget_get_style_context(GTK_WIDGET(treeview)), GTK_STATE_FLAG_NORMAL, "font", &desc, NULL); ppc.desc = pango_font_description_copy(desc); DB( g_print("family: %s\n", pango_font_description_get_family(desc)) ); DB( g_print("size: %d (%d)\n", pango_font_description_get_size (desc), pango_font_description_get_size (desc )/PANGO_SCALE) ); /* header is 1 line for date page number at top, then a title in bold, then 2 empty lines */ gint header_height = PDF_FONT_NORMAL * 2 + PDF_FONT_TITLE; gint nb_lines = gtk_tree_model_iter_n_children(model, NULL); /* should include here the headertitle line */ gint lpp = floor ((height-header_height-ppc.mt-ppc.mb) / (PDF_FONT_NORMAL + PDF_LINE_MARGIN)); gint page, num_pages = (nb_lines - 1) / lpp + 1; DB( g_print("\n - should pdf %d lines, lpp=%d, num_pages=%d\n", nb_lines, lpp, num_pages) ); gint tot_lines = 0; gint cur_page_line = 1; gchar dbuffer[255]; gchar amtbuf[G_ASCII_DTOSTR_BUF_SIZE]; gchar balbuf[G_ASCII_DTOSTR_BUF_SIZE]; GDate *date = g_date_new (); //cairo_set_font_size(cr, PDF_FONT_NORMAL); pango_font_description_set_absolute_size(ppc.desc, PDF_FONT_NORMAL * PANGO_SCALE); pango_layout_set_font_description (layout, ppc.desc); /* reset struct */ hb_pdf_set_col_title(&ppc); for(col=0;col<PDF_NUMCOL;col++) { int tw, th; ppc.column_width[col] = 0; pango_layout_set_text (layout, ppc.column_txt[col], -1); pango_layout_get_size (layout, &tw, &th); ppc.column_width[col] = MAX(ppc.column_width[col], tw / PANGO_SCALE); } DB( g_print(" - compute width\n") ); /* first pass to get max width */ valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter); while (valid) { Transaction *txn; int tw, th; gtk_tree_model_get (model, &iter, LST_DSPOPE_DATAS, &txn, -1); i = 0; g_date_set_julian (date, txn->date); g_date_strftime (dbuffer, 255-1, "%x", date); pango_layout_set_text (layout, dbuffer, -1); pango_layout_get_size (layout, &tw, &th); ppc.column_width[i] = MAX(ppc.column_width[i], tw / PANGO_SCALE); i = 1; if(txn->info != NULL && strlen(txn->info) > 0) { pango_layout_set_text (layout, txn->info, -1); pango_layout_get_size (layout, &tw, &th); ppc.column_width[i] = MAX(ppc.column_width[i], tw / PANGO_SCALE); } i = 4; hb_strfnum(amtbuf, G_ASCII_DTOSTR_BUF_SIZE-1, txn->amount, txn->kcur, GLOBALS->minor); pango_layout_set_text (layout, amtbuf, -1); pango_layout_get_size (layout, &tw, &th); ppc.column_width[i] = MAX(ppc.column_width[i], tw / PANGO_SCALE); i = 5; pango_layout_set_text (layout, "R", -1); pango_layout_get_size (layout, &tw, &th); ppc.column_width[i] = MAX(ppc.column_width[i], tw / PANGO_SCALE); i = 6; hb_strfnum(balbuf, G_ASCII_DTOSTR_BUF_SIZE-1, txn->balance, txn->kcur, GLOBALS->minor); pango_layout_set_text (layout, balbuf, -1); pango_layout_get_size (layout, &tw, &th); ppc.column_width[i] = MAX(ppc.column_width[i], tw / PANGO_SCALE); valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); } /* distribute remaining size */ gdouble tmp = pwidth - ppc.ml - ppc.mr - (PDF_COL_MARGIN*PDF_NUMCOL); DB( g_print(" page width=%f, remain width=%f\n", pwidth, tmp) ); tmp -= ppc.column_width[0]; tmp -= ppc.column_width[4]; tmp -= ppc.column_width[5]; tmp -= ppc.column_width[6]; /* info=1/4 payee=1/4 memo=2/4 */ ppc.column_width[1] = tmp / 4;; ppc.column_width[2] = tmp / 4; ppc.column_width[3] = 2*tmp / 4; DB( g_print(" page width=%f, remain width=%f\n", width, tmp) ); #if MYDEBUG == 1 for(i=0;i<PDF_NUMCOL;i++) g_print(" col%d=%g ", i, ppc.column_width[i]); g_print("\n"); #endif DB( g_print("\n - start printing\n") ); gint y; page = 1; valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(model), &iter); while (valid) { Transaction *txn; int tw, th; gtk_tree_model_get (model, &iter, LST_DSPOPE_DATAS, &txn, -1); //DB( g_print(" - %d, %d, %s\n", x, y, txn->memo) ); if(cur_page_line == 1) { //helpdraw #if HELPDRAW == 1 //page with margin hb_pdf_draw_help_rect(cr, 0xFF0000FF, ppc.ml+0.5, ppc.mt+0.5, width-(ppc.ml+ppc.mr), height - (ppc.mt+ppc.mb)); hb_pdf_draw_help_rect(cr, 0xFF00FFFF, ppc.ml+0.5, ppc.mt+0.5, width-(ppc.ml+ppc.mr), header_height); #endif cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); // draw account title pango_font_description_set_absolute_size(ppc.desc, PDF_FONT_TITLE * PANGO_SCALE); pango_layout_set_font_description (layout, ppc.desc); pango_layout_set_text (layout, accname, -1); pango_layout_get_pixel_size (layout, &tw, &th); cairo_move_to(cr, pwidth/2 - (tw/2), ppc.mt); pango_cairo_show_layout (cr, layout); // draw column titles pango_font_description_set_absolute_size(ppc.desc, PDF_FONT_NORMAL * PANGO_SCALE); pango_layout_set_font_description (layout, ppc.desc); g_sprintf(dbuffer, "Page %d/%d", page, num_pages); pango_layout_set_text (layout, dbuffer, -1); pango_layout_get_pixel_size (layout, &tw, &th); cairo_move_to(cr, pwidth - ppc.mr - tw, ppc.mt); pango_cairo_show_layout (cr, layout); //x = ppc.ml; y = ppc.mt + header_height - (PDF_FONT_NORMAL + PDF_LINE_MARGIN); hb_pdf_set_col_title(&ppc); hb_pdf_draw_line(&ppc, cr, y, TRUE, FALSE); } /* print a single line */ //x = ppc.ml; y = ppc.mt + header_height + (cur_page_line * (PDF_FONT_NORMAL + PDF_LINE_MARGIN)); /* reset struct */ for(i=0;i<PDF_NUMCOL;i++) { ppc.column_txt[i] = NULL; } i = 0; g_date_set_julian (date, txn->date); g_date_strftime (dbuffer, 255-1, "%x", date); ppc.column_txt[i] = dbuffer; i = 1; ppc.column_txt[i] = txn->info; i = 2; Payee *p = da_pay_get(txn->kpay); if(p) ppc.column_txt[i] = p->name; i = 3; /*Category *c = da_cat_get(txn->kcat); if(c) ppc.column_txt[i] = da_cat_get_fullname(c);*/ ppc.column_txt[i] = txn->memo; i = 4; hb_strfnum(amtbuf, G_ASCII_DTOSTR_BUF_SIZE-1, txn->amount, txn->kcur, GLOBALS->minor); ppc.column_txt[i] = amtbuf; i = 5; ppc.column_txt[i] = ""; if(txn->status == TXN_STATUS_CLEARED) ppc.column_txt[i] = "c"; else if(txn->status == TXN_STATUS_RECONCILED) ppc.column_txt[i] = "R"; i = 6; hb_strfnum(balbuf, G_ASCII_DTOSTR_BUF_SIZE-1, txn->balance, txn->kcur, GLOBALS->minor); ppc.column_txt[i] = balbuf; hb_pdf_draw_line(&ppc, cr, y, FALSE, (cur_page_line % 2)); /* free any fullcat name */ /*if(ppc.column_txt[3] != NULL) g_free(ppc.column_txt[3]);*/ /* export page */ if(cur_page_line >= lpp) { DB( g_print("\n - next page %d\n", page) ); cairo_show_page(cr); cur_page_line = 0; page++; } cur_page_line++; tot_lines++; valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(model), &iter); } g_date_free(date); g_object_unref (layout); pango_font_description_free (ppc.desc); cairo_destroy (cr); cairo_surface_destroy (surf); }
static void write_text_full ( cairo_t* cr, const char *txt, PangoFontDescription *font, const float x, const float y, const float ang, const int align, const float * const col) { int tw, th; cairo_save(cr); PangoLayout * pl = pango_cairo_create_layout(cr); pango_layout_set_font_description(pl, font); if (strncmp(txt, "<markup>", 8)) { pango_layout_set_text(pl, txt, -1); } else { pango_layout_set_markup(pl, txt, -1); } pango_layout_get_pixel_size(pl, &tw, &th); cairo_translate (cr, rintf(x), rintf(y)); if (ang != 0) { cairo_rotate (cr, ang); } switch(abs(align)) { case 1: cairo_translate (cr, -tw, ceil(th/-2.0)); pango_layout_set_alignment (pl, PANGO_ALIGN_RIGHT); break; case 2: cairo_translate (cr, ceil(tw/-2.0), ceil(th/-2.0)); pango_layout_set_alignment (pl, PANGO_ALIGN_CENTER); break; case 3: cairo_translate (cr, 0, ceil(th/-2.0)); pango_layout_set_alignment (pl, PANGO_ALIGN_LEFT); break; case 4: cairo_translate (cr, -tw, -th); pango_layout_set_alignment (pl, PANGO_ALIGN_RIGHT); break; case 5: cairo_translate (cr, ceil(tw/-2.0), -th); pango_layout_set_alignment (pl, PANGO_ALIGN_CENTER); break; case 6: cairo_translate (cr, 0, -th); pango_layout_set_alignment (pl, PANGO_ALIGN_LEFT); break; case 7: cairo_translate (cr, -tw, 0); pango_layout_set_alignment (pl, PANGO_ALIGN_RIGHT); break; case 8: cairo_translate (cr, ceil(tw/-2.0), 0); pango_layout_set_alignment (pl, PANGO_ALIGN_CENTER); break; case 9: cairo_translate (cr, 0, 0); pango_layout_set_alignment (pl, PANGO_ALIGN_LEFT); break; default: break; } if (align < 0) { cairo_set_source_rgba (cr, .0, .0, .0, .5); cairo_rectangle (cr, 0, 0, tw, th); cairo_fill (cr); } #if 1 cairo_set_source_rgba (cr, col[0], col[1], col[2], col[3]); pango_cairo_show_layout(cr, pl); #else cairo_set_source_rgba (cr, col[0], col[1], col[2], col[3]); pango_cairo_layout_path(cr, pl); cairo_fill(cr); #endif g_object_unref(pl); cairo_restore(cr); cairo_new_path (cr); }
/** * Sends the given character to the terminal at the given row and column, * rendering the character immediately. This bypasses the guac_terminal_display * mechanism and is intended for flushing of updates only. */ int __guac_terminal_set(guac_terminal_display* display, int row, int col, int codepoint) { int width; int bytes; char utf8[4]; /* Use foreground color */ const guac_terminal_color* color = &display->glyph_foreground; /* Use background color */ const guac_terminal_color* background = &display->glyph_background; cairo_surface_t* surface; cairo_t* cairo; int surface_width, surface_height; PangoLayout* layout; int layout_width, layout_height; int ideal_layout_width, ideal_layout_height; /* Calculate width in columns */ width = wcwidth(codepoint); if (width < 0) width = 1; /* Do nothing if glyph is empty */ if (width == 0) return 0; /* Convert to UTF-8 */ bytes = guac_terminal_encode_utf8(codepoint, utf8); surface_width = width * display->char_width; surface_height = display->char_height; ideal_layout_width = surface_width * PANGO_SCALE; ideal_layout_height = surface_height * PANGO_SCALE; /* Prepare surface */ surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, surface_width, surface_height); cairo = cairo_create(surface); /* Fill background */ cairo_set_source_rgb(cairo, background->red / 255.0, background->green / 255.0, background->blue / 255.0); cairo_rectangle(cairo, 0, 0, surface_width, surface_height); cairo_fill(cairo); /* Get layout */ layout = pango_cairo_create_layout(cairo); pango_layout_set_font_description(layout, display->font_desc); pango_layout_set_text(layout, utf8, bytes); pango_layout_set_alignment(layout, PANGO_ALIGN_CENTER); pango_layout_get_size(layout, &layout_width, &layout_height); /* If layout bigger than available space, scale it back */ if (layout_width > ideal_layout_width || layout_height > ideal_layout_height) { double scale = fmin(ideal_layout_width / (double) layout_width, ideal_layout_height / (double) layout_height); cairo_scale(cairo, scale, scale); /* Update layout to reflect scaled surface */ pango_layout_set_width(layout, ideal_layout_width / scale); pango_layout_set_height(layout, ideal_layout_height / scale); pango_cairo_update_layout(cairo, layout); } /* Draw */ cairo_set_source_rgb(cairo, color->red / 255.0, color->green / 255.0, color->blue / 255.0); cairo_move_to(cairo, 0.0, 0.0); pango_cairo_show_layout(cairo, layout); /* Draw */ guac_common_surface_draw(display->display_surface, display->char_width * col, display->char_height * row, surface); /* Free all */ g_object_unref(layout); cairo_destroy(cairo); cairo_surface_destroy(surface); return 0; }
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const { cairo_t* cr = context->platformContext(); cairo_save(cr); cairo_translate(cr, point.x(), point.y()); PangoLayout* layout = pango_cairo_create_layout(cr); setPangoAttributes(this, run, layout); gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length()); pango_layout_set_text(layout, utf8, -1); // Our layouts are single line PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0); GdkRegion* partialRegion = NULL; if (to - from != run.length()) { // Clip the region of the run to be rendered char* start = g_utf8_offset_to_pointer(utf8, from); char* end = g_utf8_offset_to_pointer(start, to - from); int ranges[] = {start - utf8, end - utf8}; partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1); gdk_region_shrink(partialRegion, 0, -pixelSize()); } Color fillColor = context->fillColor(); float red, green, blue, alpha; // Text shadow, inspired by FontMac IntSize shadowSize; int shadowBlur = 0; Color shadowColor; bool hasShadow = context->textDrawingMode() == cTextFill && context->getShadow(shadowSize, shadowBlur, shadowColor); // TODO: Blur support if (hasShadow) { // Disable graphics context shadows (not yet implemented) and paint them manually context->clearShadow(); Color shadowFillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), shadowColor.alpha() * fillColor.alpha() / 255); cairo_save(cr); shadowFillColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); cairo_translate(cr, shadowSize.width(), shadowSize.height()); if (partialRegion) { gdk_cairo_region(cr, partialRegion); cairo_clip(cr); } pango_cairo_show_layout_line(cr, layoutLine); cairo_restore(cr); } fillColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); if (partialRegion) { gdk_cairo_region(cr, partialRegion); cairo_clip(cr); } pango_cairo_show_layout_line(cr, layoutLine); if (context->textDrawingMode() & cTextStroke) { Color strokeColor = context->strokeColor(); strokeColor.getRGBA(red, green, blue, alpha); cairo_set_source_rgba(cr, red, green, blue, alpha); pango_cairo_layout_line_path(cr, layoutLine); cairo_set_line_width(cr, context->strokeThickness()); cairo_stroke(cr); } // Re-enable the platform shadow we disabled earlier if (hasShadow) context->setShadow(shadowSize, shadowBlur, shadowColor); // Pango sometimes leaves behind paths we don't want cairo_new_path(cr); if (partialRegion) gdk_region_destroy(partialRegion); g_free(utf8); g_object_unref(layout); cairo_restore(cr); }
void *dt_control_expose(void *voidptr) { int width, height, pointerx, pointery; if(!darktable.gui->surface) return NULL; width = dt_cairo_image_surface_get_width(darktable.gui->surface); height = dt_cairo_image_surface_get_height(darktable.gui->surface); GtkWidget *widget = dt_ui_center(darktable.gui->ui); #if GTK_CHECK_VERSION(3, 20, 0) gdk_window_get_device_position(gtk_widget_get_window(widget), gdk_seat_get_pointer(gdk_display_get_default_seat(gtk_widget_get_display(widget))), &pointerx, &pointery, NULL); #else GdkDevice *device = gdk_device_manager_get_client_pointer(gdk_display_get_device_manager(gtk_widget_get_display(widget))); gdk_window_get_device_position(gtk_widget_get_window(widget), device, &pointerx, &pointery, NULL); #endif // create a gtk-independent surface to draw on cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); // TODO: control_expose: only redraw the part not overlapped by temporary control panel show! // float tb = 8; // fmaxf(10, width/100.0); darktable.control->tabborder = tb; darktable.control->width = width; darktable.control->height = height; GdkRGBA color; GtkStyleContext *context = gtk_widget_get_style_context(widget); gboolean color_found = gtk_style_context_lookup_color (context, "bg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_set_line_width(cr, tb); cairo_rectangle(cr, tb / 2., tb / 2., width - tb, height - tb); cairo_stroke(cr); cairo_set_line_width(cr, 1.5); color_found = gtk_style_context_lookup_color (context, "really_dark_bg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_rectangle(cr, tb, tb, width - 2 * tb, height - 2 * tb); cairo_stroke(cr); cairo_save(cr); cairo_translate(cr, tb, tb); cairo_rectangle(cr, 0, 0, width - 2 * tb, height - 2 * tb); cairo_clip(cr); cairo_new_path(cr); // draw view dt_view_manager_expose(darktable.view_manager, cr, width - 2 * tb, height - 2 * tb, pointerx - tb, pointery - tb); cairo_restore(cr); // draw log message, if any dt_pthread_mutex_lock(&darktable.control->log_mutex); if(darktable.control->log_ack != darktable.control->log_pos) { PangoRectangle ink; PangoLayout *layout; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); const float fontsize = DT_PIXEL_APPLY_DPI(14); pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, desc); pango_layout_set_text(layout, darktable.control->log_message[darktable.control->log_ack], -1); pango_layout_get_pixel_extents(layout, &ink, NULL); const float pad = DT_PIXEL_APPLY_DPI(20.0f), xc = width / 2.0; const float yc = height * 0.85 + DT_PIXEL_APPLY_DPI(10), wd = pad + ink.width * .5f; float rad = DT_PIXEL_APPLY_DPI(14); cairo_set_line_width(cr, 1.); cairo_move_to(cr, xc - wd, yc + rad); for(int k = 0; k < 5; k++) { cairo_arc(cr, xc - wd, yc, rad, M_PI / 2.0, 3.0 / 2.0 * M_PI); cairo_line_to(cr, xc + wd, yc - rad); cairo_arc(cr, xc + wd, yc, rad, 3.0 * M_PI / 2.0, M_PI / 2.0); cairo_line_to(cr, xc - wd, yc + rad); if(k == 0) { color_found = gtk_style_context_lookup_color (context, "selected_bg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_fill_preserve(cr); } cairo_set_source_rgba(cr, 0., 0., 0., 1.0 / (1 + k)); cairo_stroke(cr); rad += .5f; } color_found = gtk_style_context_lookup_color (context, "fg_color", &color); if(!color_found) { color.red = 1.0; color.green = 0.0; color.blue = 0.0; color.alpha = 1.0; } gdk_cairo_set_source_rgba(cr, &color); cairo_move_to(cr, xc - wd + .5f * pad, (yc + 1. / 3. * fontsize) - fontsize); pango_cairo_show_layout(cr, layout); pango_font_description_free(desc); g_object_unref(layout); } // draw busy indicator if(darktable.control->log_busy > 0) { PangoRectangle ink; PangoLayout *layout; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); const float fontsize = DT_PIXEL_APPLY_DPI(14); pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, desc); pango_layout_set_text(layout, _("working.."), -1); pango_layout_get_pixel_extents(layout, &ink, NULL); const float xc = width / 2.0, yc = height * 0.85 - DT_PIXEL_APPLY_DPI(30), wd = ink.width * .5f; cairo_move_to(cr, xc - wd, yc + 1. / 3. * fontsize - fontsize); pango_cairo_layout_path(cr, layout); cairo_set_source_rgb(cr, 0.7, 0.7, 0.7); cairo_fill_preserve(cr); cairo_set_line_width(cr, 0.7); cairo_set_source_rgb(cr, 0.3, 0.3, 0.3); cairo_stroke(cr); pango_font_description_free(desc); g_object_unref(layout); } dt_pthread_mutex_unlock(&darktable.control->log_mutex); cairo_destroy(cr); cairo_t *cr_pixmap = cairo_create(darktable.gui->surface); cairo_set_source_surface(cr_pixmap, cst, 0, 0); cairo_paint(cr_pixmap); cairo_destroy(cr_pixmap); cairo_surface_destroy(cst); return NULL; }
static GdkPixbuf * create_gallery (ThumbApp *app) { GdkPixbuf *screenshot, *pixbuf = NULL; cairo_t *cr; cairo_surface_t *surface; PangoLayout *layout; PangoFontDescription *font_desc; gint64 stream_length, screenshot_interval, pos; guint columns = 3, rows, current_column, current_row, x, y; gint screenshot_width = 0, screenshot_height = 0, x_padding = 0, y_padding = 0; gfloat scale = 1.0; gchar *header_text, *duration_text, *filename; GFile *file; /* Calculate how many screenshots we're going to take */ stream_length = app->duration; /* As a default, we have one screenshot per minute of stream, * but adjusted so we don't have any gaps in the resulting gallery. */ if (gallery == 0) { gallery = stream_length / 60000; while (gallery % 3 != 0 && gallery % 4 != 0 && gallery % 5 != 0) { gallery++; } } if (gallery < GALLERY_MIN) gallery = GALLERY_MIN; if (gallery > GALLERY_MAX) gallery = GALLERY_MAX; screenshot_interval = stream_length / gallery; /* Put a lower bound on the screenshot interval so we can't enter an infinite loop below */ if (screenshot_interval == 0) screenshot_interval = 1; g_debug ("Producing gallery of %u screenshots, taken at %" G_GINT64_FORMAT " millisecond intervals throughout a %" G_GINT64_FORMAT " millisecond-long stream.", gallery, screenshot_interval, stream_length); /* Calculate how to arrange the screenshots so we don't get ones orphaned on the last row. * At this point, only deal with arrangements of 3, 4 or 5 columns. */ y = G_MAXUINT; for (x = 3; x <= 5; x++) { if (gallery % x == 0 || x - gallery % x < y) { y = x - gallery % x; columns = x; /* Have we found an optimal solution already? */ if (y == x) break; } } rows = ceil ((gfloat) gallery / (gfloat) columns); g_debug ("Outputting as %u rows and %u columns.", rows, columns); /* Take the screenshots and composite them into a pixbuf */ current_column = current_row = x = y = 0; for (pos = screenshot_interval; pos <= stream_length; pos += screenshot_interval) { if (pos == stream_length) screenshot = capture_frame_at_time (app, pos - 1); else screenshot = capture_frame_at_time (app, pos); if (pixbuf == NULL) { screenshot_width = gdk_pixbuf_get_width (screenshot); screenshot_height = gdk_pixbuf_get_height (screenshot); /* Calculate a scaling factor so that screenshot_width -> output_size */ scale = (float) output_size / (float) screenshot_width; x_padding = x = MAX (output_size * 0.05, 1); y_padding = y = MAX (scale * screenshot_height * 0.05, 1); g_debug ("Scaling each screenshot by %f.", scale); /* Create our massive pixbuf */ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, columns * output_size + (columns + 1) * x_padding, (guint) (rows * scale * screenshot_height + (rows + 1) * y_padding)); gdk_pixbuf_fill (pixbuf, 0x000000ff); g_debug ("Created output pixbuf (%ux%u).", gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf)); } /* Composite the screenshot into our gallery */ gdk_pixbuf_composite (screenshot, pixbuf, x, y, output_size, scale * screenshot_height, (gdouble) x, (gdouble) y, scale, scale, GDK_INTERP_BILINEAR, 255); g_object_unref (screenshot); g_debug ("Composited screenshot from %" G_GINT64_FORMAT " milliseconds (address %u) at (%u,%u).", pos, GPOINTER_TO_UINT (screenshot), x, y); /* We print progress in the range 10% (MIN_PROGRESS) to 50% (MAX_PROGRESS - MIN_PROGRESS) / 2.0 */ PRINT_PROGRESS (MIN_PROGRESS + (current_row * columns + current_column) * (((MAX_PROGRESS - MIN_PROGRESS) / gallery) / 2.0)); current_column = (current_column + 1) % columns; x += output_size + x_padding; if (current_column == 0) { x = x_padding; y += scale * screenshot_height + y_padding; current_row++; } } g_debug ("Converting pixbuf to a Cairo surface."); /* Load the pixbuf into a Cairo surface and overlay the text. The height is the height of * the gallery plus the necessary height for 3 lines of header (at ~18px each), plus some * extra padding. */ surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf) + GALLERY_HEADER_HEIGHT + y_padding); cr = cairo_create (surface); cairo_surface_destroy (surface); /* First, copy across the gallery pixbuf */ gdk_cairo_set_source_pixbuf (cr, pixbuf, 0.0, GALLERY_HEADER_HEIGHT + y_padding); cairo_rectangle (cr, 0.0, GALLERY_HEADER_HEIGHT + y_padding, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf)); cairo_fill (cr); g_object_unref (pixbuf); /* Build the header information */ duration_text = totem_time_to_string (stream_length, FALSE, FALSE); file = g_file_new_for_commandline_arg (app->input); filename = g_file_get_basename (file); g_object_unref (file); /* Translators: The first string is "Filename" (as translated); the second is an actual filename. The third string is "Resolution" (as translated); the fourth and fifth are screenshot height and width, respectively. The sixth string is "Duration" (as translated); the seventh is the movie duration in words. */ header_text = g_markup_printf_escaped (_("<b>%s</b>: %s\n<b>%s</b>: %d\303\227%d\n<b>%s</b>: %s"), _("Filename"), filename, _("Resolution"), screenshot_width, screenshot_height, _("Duration"), duration_text); g_free (duration_text); g_free (filename); g_debug ("Writing header text with Pango."); /* Write out some header information */ layout = pango_cairo_create_layout (cr); font_desc = pango_font_description_from_string ("Sans 18px"); pango_layout_set_font_description (layout, font_desc); pango_font_description_free (font_desc); pango_layout_set_markup (layout, header_text, -1); g_free (header_text); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */ cairo_move_to (cr, (gdouble) x_padding, (gdouble) y_padding); pango_cairo_show_layout (cr, layout); /* Go through each screenshot and write its timestamp */ current_column = current_row = 0; x = x_padding + output_size; y = y_padding * 2 + GALLERY_HEADER_HEIGHT + scale * screenshot_height; font_desc = pango_font_description_from_string ("Sans 10px"); pango_layout_set_font_description (layout, font_desc); pango_font_description_free (font_desc); g_debug ("Writing screenshot timestamps with Pango."); for (pos = screenshot_interval; pos <= stream_length; pos += screenshot_interval) { gchar *timestamp_text; gint layout_width, layout_height; timestamp_text = totem_time_to_string (pos, FALSE, FALSE); pango_layout_set_text (layout, timestamp_text, -1); pango_layout_get_pixel_size (layout, &layout_width, &layout_height); /* Display the timestamp in the bottom-right corner of the current screenshot */ cairo_move_to (cr, x - layout_width - 0.02 * output_size, y - layout_height - 0.02 * scale * screenshot_height); /* We have to stroke the text so it's visible against screenshots of the same * foreground color. */ pango_cairo_layout_path (cr, layout); cairo_set_source_rgb (cr, 0.0, 0.0, 0.0); /* black */ cairo_stroke_preserve (cr); cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */ cairo_fill (cr); g_debug ("Writing timestamp \"%s\" at (%f,%f).", timestamp_text, x - layout_width - 0.02 * output_size, y - layout_height - 0.02 * scale * screenshot_height); /* We print progress in the range 50% (MAX_PROGRESS - MIN_PROGRESS) / 2.0) to 90% (MAX_PROGRESS) */ PRINT_PROGRESS (MIN_PROGRESS + (MAX_PROGRESS - MIN_PROGRESS) / 2.0 + (current_row * columns + current_column) * (((MAX_PROGRESS - MIN_PROGRESS) / gallery) / 2.0)); g_free (timestamp_text); current_column = (current_column + 1) % columns; x += output_size + x_padding; if (current_column == 0) { x = x_padding + output_size; y += scale * screenshot_height + y_padding; current_row++; } } g_object_unref (layout); g_debug ("Converting Cairo surface back to pixbuf."); /* Create a new pixbuf from the Cairo context */ pixbuf = cairo_surface_to_pixbuf (cairo_get_target (cr)); cairo_destroy (cr); return pixbuf; }
static gboolean _togglebutton_draw(GtkWidget *widget, cairo_t *cr) { g_return_val_if_fail(widget != NULL, FALSE); g_return_val_if_fail(DTGTK_IS_TOGGLEBUTTON(widget), FALSE); GtkDarktableToggleButton *button = DTGTK_TOGGLEBUTTON(widget); GtkStateFlags state = gtk_widget_get_state_flags(widget); GdkRGBA bg_color, fg_color; GtkStyleContext *context = gtk_widget_get_style_context(widget); if(button->icon_flags & CPF_CUSTOM_BG) bg_color = button->bg; else { GdkRGBA *bc; gtk_style_context_get(context, state, "background-color", &bc, NULL); bg_color = *bc; gdk_rgba_free(bc); } if(button->icon_flags & CPF_CUSTOM_FG) fg_color = button->fg; else gtk_style_context_get_color(context, state, &fg_color); /* fetch flags */ int flags = DTGTK_TOGGLEBUTTON(widget)->icon_flags; /* set inner border */ int border = DT_PIXEL_APPLY_DPI((flags & CPF_DO_NOT_USE_BORDER) ? 2 : 6); /* update active state paint flag */ gboolean active = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)); if(active) flags |= CPF_ACTIVE; else flags &= ~(CPF_ACTIVE); /* prelight */ if(state & GTK_STATE_FLAG_PRELIGHT) flags |= CPF_PRELIGHT; else flags &= ~CPF_PRELIGHT; /* begin cairo drawing */ GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width; int height = allocation.height; /* draw standard button background if not transparent nor flat styled */ if((flags & CPF_STYLE_FLAT)) { if(flags & CPF_PRELIGHT || flags & CPF_ACTIVE) { cairo_rectangle(cr, 0, 0, width, height); gdk_cairo_set_source_rgba(cr, &bg_color); cairo_fill(cr); } } else if(!(flags & CPF_BG_TRANSPARENT)) { /* draw default boxed button */ gtk_render_background(context, cr, 0, 0, width, height); if(!(flags & CPF_DO_NOT_USE_BORDER)) gtk_render_frame(context, cr, 0, 0, width, height); } /* create pango text settings if label exists */ PangoLayout *layout = NULL; int pw = 0, ph = 0; const gchar *text = gtk_button_get_label(GTK_BUTTON(widget)); if(text) { layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, darktable.bauhaus->pango_font_desc); pango_cairo_context_set_resolution(pango_layout_get_context(layout), darktable.gui->dpi); pango_layout_set_text(layout, text, -1); pango_layout_get_pixel_size(layout, &pw, &ph); } gdk_cairo_set_source_rgba(cr, &fg_color); /* draw icon */ if(DTGTK_TOGGLEBUTTON(widget)->icon) { // if (flags & CPF_IGNORE_FG_STATE) // state = GTK_STATE_NORMAL; int icon_width = text ? height - (border * 2) : width - (border * 2); int icon_height = height - (border * 2); if(icon_width > 0 && icon_height > 0) { if(text) DTGTK_TOGGLEBUTTON(widget) ->icon(cr, border, border, height - (border * 2), height - (border * 2), flags); else DTGTK_TOGGLEBUTTON(widget) ->icon(cr, border, border, width - (border * 2), height - (border * 2), flags); } } /* draw label */ if(text) { int lx = DT_PIXEL_APPLY_DPI(2), ly = ((height / 2.0) - (ph / 2.0)); // if (DTGTK_TOGGLEBUTTON (widget)->icon) lx += width; // GdkRectangle t={x,y,x+width,y+height}; // gtk_paint_layout(style,gtk_widget_get_window(widget), // state,TRUE,&t,widget,"togglebutton",lx,ly,layout); cairo_translate(cr, lx, ly); pango_cairo_show_layout(cr, layout); g_object_unref(layout); } return FALSE; }
/* Convenience */ static VALUE rg_create_pango_layout(VALUE self) { return GOBJ2RVAL_UNREF(pango_cairo_create_layout(RVAL2CRCONTEXT(self))); }
gboolean cd_do_render_listing_notification (gpointer pUserData, CDListing *pListing, cairo_t *pCairoContext) { //g_print ("%s ()\n", __func__); int iWidth = pListing->container.iWidth, iHeight = pListing->container.iHeight; int iLeftMargin = myDialogs.dialogTextDescription.iSize + 2, iRightMargin = (myDialogs.dialogTextDescription.iSize + 2) / 2; int iTopMargin = (myDialogs.dialogTextDescription.iSize + 2) + GAP, iBottomMargin = (myDialogs.dialogTextDescription.iSize + 2) * 4 + GAP; CDEntry *pEntry; // on dessine un cadre et un fond double fRadius = MIN (6, myDialogs.dialogTextDescription.iSize/2+1); double fLineWidth = 1.; cairo_set_line_width (pCairoContext, fLineWidth); cairo_save (pCairoContext); cairo_translate (pCairoContext, 0, fLineWidth); cairo_dock_draw_rounded_rectangle (pCairoContext, fRadius, fLineWidth, iWidth - 2 * fRadius - fLineWidth, iTopMargin - GAP); cairo_set_source_rgba (pCairoContext, .8, .8, 1., 1.); cairo_stroke_preserve (pCairoContext); cairo_set_source_rgba (pCairoContext, 1., 1., 1., .7); cairo_fill (pCairoContext); cairo_translate (pCairoContext, 0, iTopMargin + fLineWidth); cairo_dock_draw_rounded_rectangle (pCairoContext, fRadius, fLineWidth, iWidth - 2 * fRadius - fLineWidth, iHeight - iTopMargin - iBottomMargin - GAP); cairo_set_source_rgba (pCairoContext, .8, .8, 1., 1.); cairo_stroke_preserve (pCairoContext); cairo_set_source_rgba (pCairoContext, 1., 1., 1., .7); cairo_fill (pCairoContext); cairo_translate (pCairoContext, 0, iHeight - iTopMargin - 2*fLineWidth - iBottomMargin + GAP); cairo_dock_draw_rounded_rectangle (pCairoContext, fRadius, fLineWidth, iWidth - 2 * fRadius - fLineWidth, iBottomMargin - GAP - fLineWidth); cairo_set_source_rgba (pCairoContext, .8, .8, 1., 1.); cairo_stroke_preserve (pCairoContext); cairo_set_source_rgba (pCairoContext, 1., 1., 1., .7); cairo_fill (pCairoContext); cairo_restore (pCairoContext); PangoLayout *pLayout = pango_cairo_create_layout (pCairoContext); PangoFontDescription *pDesc = pango_font_description_new (); pango_font_description_set_absolute_size (pDesc, myDialogs.dialogTextDescription.iSize * PANGO_SCALE); pango_font_description_set_family_static (pDesc, myDialogs.dialogTextDescription.cFont); pango_font_description_set_weight (pDesc, myDialogs.dialogTextDescription.iWeight); pango_font_description_set_style (pDesc, myLabels.iconTextDescription.iStyle); pango_layout_set_font_description (pLayout, pDesc); pango_font_description_free (pDesc); // on dessine les entrees. if (pListing->pEntries != NULL) { // on dessine chaque entree. int iNbSteps = _listing_compute_nb_steps (pListing); // nb d'etapes pour l'apparition du texte. int iOffsetX = NB_STEPS_FOR_1_ENTRY - (iNbSteps - pListing->iAppearanceAnimationCount) - 1; if (pListing->iNbEntries >= myConfig.iNbLinesInListing) iOffsetX += myConfig.iNbLinesInListing/4*NB_STEPS_LATE; // permet de donner une transparence aux 25% dernieres lignes. double dx, dy, dm = myConfig.iNbLinesInListing * (myDialogs.dialogTextDescription.iSize + 2) / 2; dm = 0; dy = iTopMargin - pListing->fCurrentOffset + 1 + dm; double ymax = MIN (iTopMargin + pListing->iNbEntries * (myDialogs.dialogTextDescription.iSize + 2), iHeight - iBottomMargin); GList *e; for (e = pListing->pEntries; e != NULL; e = e->next) { if (iOffsetX >= NB_STEPS_FOR_1_ENTRY) // en dehors a droite a partir de celui-ci. break ; pEntry = e->data; if (pEntry->bHidden) continue ; dx = myDialogs.dialogTextDescription.iSize + 2; // marge a gauche. //if (iOffsetX > 0 && pListing->iAppearanceAnimationCount > 0) // dx += (double) iOffsetX * (iWidth - (myDialogs.dialogTextDescription.iSize + 2)) / NB_STEPS_FOR_1_ENTRY; dy += (myDialogs.dialogTextDescription.iSize + 2); while (dy + myDialogs.dialogTextDescription.iSize + 2 <= iTopMargin + 1) dy += pListing->iNbEntries * (myDialogs.dialogTextDescription.iSize + 2); while (dy > ymax) dy -= pListing->iNbEntries * (myDialogs.dialogTextDescription.iSize + 2); if (dy > ymax || dy + myDialogs.dialogTextDescription.iSize + 2 <= iTopMargin + 1) continue; cairo_save (pCairoContext); cairo_translate (pCairoContext, dx, dy); // on fait un clip si necessaire. if (dy + myDialogs.dialogTextDescription.iSize + 2 > iHeight - iBottomMargin || dy < iTopMargin) // cette entree n'est que partiellement visible. { if (dy < iTopMargin) // elle depasse en haut. cairo_rectangle (pCairoContext, -iLeftMargin, iTopMargin - dy, iWidth, myDialogs.dialogTextDescription.iSize + 2 -(iTopMargin - dy)); else // elle depasse en bas. cairo_rectangle (pCairoContext, -iLeftMargin, 0, iWidth, iHeight - iBottomMargin - dy); cairo_clip (pCairoContext); } // on dessine l'icone. if (pEntry->pIconSurface != NULL) { cairo_set_source_surface (pCairoContext, pEntry->pIconSurface, - iLeftMargin + 1, 0.); cairo_paint (pCairoContext); } // on souligne l'entree courante. if (e == pListing->pCurrentEntry) { double f = 1. - (double) pListing->iCurrentEntryAnimationCount / NB_STEPS_FOR_CURRENT_ENTRY; if (f != 0) { cairo_save (pCairoContext); double rx = .5*(iWidth - iLeftMargin - iRightMargin); double ry = .5*(myDialogs.dialogTextDescription.iSize + 2); cairo_pattern_t *pPattern = cairo_pattern_create_radial (ry, ry, 0., ry, ry, f * ry); cairo_pattern_set_extend (pPattern, CAIRO_EXTEND_NONE); cairo_pattern_add_color_stop_rgba (pPattern, 0., 0., 0., 1., .3); cairo_pattern_add_color_stop_rgba (pPattern, 1., 0., 0., 0., 0.); cairo_scale (pCairoContext, rx/ry, 1.); cairo_set_source (pCairoContext, pPattern); cairo_paint (pCairoContext); cairo_pattern_destroy (pPattern); cairo_restore (pCairoContext); // on dessine l'indicateur de sous-listing. if (pEntry->list != NULL) { cairo_set_source_rgba (pCairoContext, 0., 0., 0., f); cairo_move_to (pCairoContext, iWidth - iLeftMargin - iRightMargin, myDialogs.dialogTextDescription.iSize/4); cairo_rel_line_to (pCairoContext, iRightMargin, myDialogs.dialogTextDescription.iSize/4); cairo_rel_line_to (pCairoContext, -iRightMargin, myDialogs.dialogTextDescription.iSize/4); cairo_close_path (pCairoContext); cairo_stroke (pCairoContext); } } } // on dessine le texte. cairo_set_source_rgba (pCairoContext, 0., 0., 0., 1. - (double) iOffsetX / NB_STEPS_FOR_1_ENTRY); pango_layout_set_text (pLayout, pEntry->cName, -1); pango_cairo_show_layout (pCairoContext, pLayout); // on separe la 1ere entree de la derniere. if (e->prev == NULL) { cairo_set_source_rgba (pCairoContext, 0., 0., 0., .5); cairo_move_to (pCairoContext, 0., 1.); cairo_rel_line_to (pCairoContext, iWidth - iLeftMargin - iRightMargin, 0.); double dashes = 2.; cairo_set_dash (pCairoContext, &dashes, 1, 0.); cairo_stroke (pCairoContext); cairo_set_dash (pCairoContext, &dashes, 0, 0.); } cairo_restore (pCairoContext); iOffsetX += NB_STEPS_LATE; } // on dessine le chemin de l'entree courante. if (pListing->pCurrentEntry) { pEntry = pListing->pCurrentEntry->data; cairo_save (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); cairo_translate (pCairoContext, fRadius - pListing->iTitleOffset, 0.); pango_layout_set_text (pLayout, pEntry->cPath ? pEntry->cPath : pEntry->cName, -1); PangoRectangle ink, log; pango_layout_get_pixel_extents (pLayout, &ink, &log); pListing->iTitleWidth = ink.width; pango_cairo_show_layout (pCairoContext, pLayout); cairo_restore (pCairoContext); } } // on dessine l'etat de la recherche. cairo_translate (pCairoContext, 0, iHeight - iBottomMargin); cairo_set_source_surface (pCairoContext, myData.pScoobySurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); cairo_translate (pCairoContext, 2 * (myDialogs.dialogTextDescription.iSize + 2), GAP); if (myData.cStatus != NULL) { pango_layout_set_text (pLayout, myData.cStatus, -1); } pango_cairo_show_layout (pCairoContext, pLayout); // on dessine le filtre. cairo_translate (pCairoContext, 0., myDialogs.dialogTextDescription.iSize + 2); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_MATCH_CASE) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F1) Match case"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, iWidth/3, 0.); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_MUSIC) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F2) Music"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, iWidth/3, 0.); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_IMAGE) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F3) Image"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, -2*iWidth/3, myDialogs.dialogTextDescription.iSize + 2); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_VIDEO) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F4) Video"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, iWidth/3, 0.); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_TEXT) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F5) Text"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, iWidth/3, 0.); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_HTML) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F6) Html"), -1); pango_cairo_show_layout (pCairoContext, pLayout); cairo_translate (pCairoContext, -2*iWidth/3, myDialogs.dialogTextDescription.iSize + 2); cairo_set_source_surface (pCairoContext, (myData.iCurrentFilter & DO_TYPE_SOURCE) ? myData.pActiveButtonSurface : myData.pInactiveButtonSurface, 0., 0.); cairo_paint (pCairoContext); cairo_set_source_rgb (pCairoContext, 0., 0., 0.); pango_layout_set_text (pLayout, D_("(F7) Sources"), -1); pango_cairo_show_layout (pCairoContext, pLayout); g_object_unref (pLayout); }
void wxSVGCanvasTextCairo::InitText(const wxString& text, const wxCSSStyleDeclaration& style, wxSVGMatrix* matrix) { BeginChar(matrix); // create path from text cairo_t* cr = ((wxSVGCanvasPathCairo*) m_char->path)->GetCr(); #if defined(__WXMSW__) || defined(__WXMAC__) int size = (int) style.GetFontSize(); int fstyle = style.GetFontStyle() == wxCSS_VALUE_ITALIC ? wxFONTSTYLE_ITALIC : (style.GetFontStyle() == wxCSS_VALUE_OBLIQUE ? wxFONTSTYLE_SLANT : wxFONTSTYLE_NORMAL); wxFontWeight weight = style.GetFontWeight() == wxCSS_VALUE_BOLD ? wxFONTWEIGHT_BOLD : style.GetFontWeight() == wxCSS_VALUE_BOLDER ? wxFONTWEIGHT_MAX : style.GetFontWeight() == wxCSS_VALUE_LIGHTER ? wxFONTWEIGHT_LIGHT : wxFONTWEIGHT_NORMAL; wxFont fnt(size, wxFONTFAMILY_DEFAULT, fstyle, weight, false, style.GetFontFamily()); #ifdef __WXMSW__ HFONT hfont = (HFONT) fnt.GetResourceHandle(); cairo_set_font_face(cr, cairo_win32_font_face_create_for_hfont(hfont)); #else CGFontRef cgFont = fnt.OSXGetCGFont(); cairo_set_font_face(cr, cairo_quartz_font_face_create_for_cgfont(cgFont)); #endif cairo_set_font_size(cr, style.GetFontSize()); cairo_font_extents_t fextents; cairo_font_extents(cr, &fextents); double maxWidth = 0; if (style.GetTextAnchor() == wxCSS_VALUE_MIDDLE || style.GetTextAnchor() == wxCSS_VALUE_END) { wxStringTokenizer tokenzr(text, wxT("\n")); while (tokenzr.HasMoreTokens()) { wxString token = tokenzr.GetNextToken(); cairo_text_extents_t extents; cairo_text_extents(cr, (const char*) token.utf8_str(), &extents); if (maxWidth < extents.width) maxWidth = extents.width; } } wxStringTokenizer tokenzr(text, wxT("\n")); double x_advance = 0; double width = 0; double height = 0; double y = 0; while (tokenzr.HasMoreTokens()) { wxString token = tokenzr.GetNextToken(); // get text extents cairo_text_extents_t extents; cairo_text_extents(cr, (const char*) token.utf8_str(), &extents); double x = style.GetTextAnchor() == wxCSS_VALUE_END ? maxWidth - extents.width : style.GetTextAnchor() == wxCSS_VALUE_MIDDLE ? (maxWidth - extents.width) / 2 : 0; m_char->path->MoveTo(m_tx + x, m_ty + y); cairo_text_path(cr, (const char*) token.utf8_str()); if (x_advance < extents.x_advance) x_advance = extents.x_advance; if (width < extents.width) width = extents.width; height += fextents.height; if (tokenzr.HasMoreTokens()) y += fextents.height; } // set bbox m_char->bbox = wxSVGRect(m_tx, m_ty, width, height); // increase current position (m_tx) if (style.GetTextAnchor() == wxCSS_VALUE_MIDDLE || style.GetTextAnchor() == wxCSS_VALUE_END) { wxSVGRect bbox = m_char->path->GetResultBBox(style); m_tx += x_advance > bbox.GetWidth() ? x_advance : bbox.GetWidth(); } else m_tx += x_advance; #else PangoLayout* layout = pango_cairo_create_layout(cr); PangoFontDescription* font = pango_font_description_new(); pango_font_description_set_family(font, style.GetFontFamily().ToAscii()); pango_font_description_set_weight(font, style.GetFontWeight() == wxCSS_VALUE_BOLD ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL); pango_font_description_set_style(font, style.GetFontStyle() == wxCSS_VALUE_ITALIC ? PANGO_STYLE_ITALIC : (style.GetFontStyle() == wxCSS_VALUE_OBLIQUE ? PANGO_STYLE_OBLIQUE : PANGO_STYLE_NORMAL)); pango_font_description_set_absolute_size(font, style.GetFontSize() * PANGO_SCALE); PangoContext* ctx = pango_layout_get_context(layout); PangoFont* f = pango_context_load_font(ctx, font); if (f == NULL) pango_font_description_set_style(font, PANGO_STYLE_NORMAL); pango_layout_set_font_description(layout, font); if (style.GetTextAnchor() != wxCSS_VALUE_START) pango_layout_set_alignment(layout, style.GetTextAnchor() == wxCSS_VALUE_MIDDLE ? PANGO_ALIGN_CENTER : PANGO_ALIGN_RIGHT); pango_layout_set_text(layout, (const char*) text.utf8_str(), -1); int baseline = pango_layout_get_baseline(layout); m_char->path->MoveTo(m_tx, m_ty - ((double)baseline / PANGO_SCALE)); pango_cairo_layout_path(cr, layout); // set bbox and increase current position (m_tx) int lwidth, lheight; pango_layout_get_size(layout, &lwidth, &lheight); double width = ((double)lwidth / PANGO_SCALE); double height = ((double)lheight / PANGO_SCALE); m_char->bbox = wxSVGRect(m_tx, m_ty, width, height); if (style.GetTextAnchor() == wxCSS_VALUE_MIDDLE || style.GetTextAnchor() == wxCSS_VALUE_END) { wxSVGRect bbox = m_char->path->GetResultBBox(style); m_tx += width > bbox.GetWidth() ? width : bbox.GetWidth(); } else m_tx += width; g_object_unref(layout); pango_font_description_free(font); #endif }
static void gtk_attractor_view_paint(GtkWidget *widget) { GtkAttractor_View *attractor_view = GTK_ATTRACTOR_VIEW(widget); int width, height; PangoLayout *layout; CairoxTextParameters text_p; char buffer[64]; cairo_t *cr; int p, c; width = widget->allocation.width; height = widget->allocation.height; cr = gdk_cairo_create(widget->window); /* Transparent background */ cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 0.0); cairo_paint(cr); //int current_attractor_i = ((iterations_so_far) && (iterations_so_far < C_MAX)) ? (iterations_so_far) : (0); layout = pango_cairo_create_layout(cr); // if (!training) { // g_snprintf(buffer, 64, "Step: %d", step_number); // cairox_text_parameters_set(&text_p, 20, height-20, PANGOX_XALIGN_LEFT, PANGOX_YALIGN_TOP, 0.0); // cairox_paint_pango_text(cr, &text_p, layout, buffer); cairo_set_source_rgb(cr, 0, 0, 0); cairo_set_line_width(cr, 1); // cairo_rectangle(cr, 20, 20, 120, 80); cairo_rectangle(cr, X_MARGIN, Y_MARGIN, width - (2.0 * X_MARGIN), height - (2.0 * Y_MARGIN)); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, 1, 1, 1); cairo_fill(cr); double n_rows = (double) (P + 6); double row_height = (height - (Y_MARGIN*2)) / n_rows; double n_columns = ATTRACTOR_LESION_LEVEL + 1.0; double column_width = (width - (X_MARGIN*2)) / n_columns; int smaller_font_size = 14, bigger_font_size = 16; if (n_rows > 36) { smaller_font_size = 12; bigger_font_size = 15; } pangox_layout_set_font_size(layout, bigger_font_size); g_snprintf(buffer, 64, "Pattern Name"); cairox_text_parameters_set(&text_p, X_MARGIN*2, row_height*2, PANGOX_XALIGN_LEFT, PANGOX_YALIGN_TOP, 0.0); cairox_paint_pango_text(cr, &text_p, layout, buffer); for (c = 0; c < ATTRACTOR_LESION_LEVEL; c++) { g_snprintf(buffer, 64, "%1.1f%% Lesioned", c * 100.0 / (double) ATTRACTOR_LESION_LEVEL); cairox_text_parameters_set(&text_p, column_width*(c+1), row_height*2, PANGOX_XALIGN_LEFT, PANGOX_YALIGN_TOP, 0.0); cairox_paint_pango_text(cr, &text_p, layout, buffer); } pangox_layout_set_font_size(layout, smaller_font_size); for (p = 0; p < P; p++) { g_snprintf(buffer, 64, "%s", get_name_string(p)); cairox_text_parameters_set(&text_p, X_MARGIN*2, (p+4)* row_height, PANGOX_XALIGN_LEFT, PANGOX_YALIGN_TOP, 0.0); cairox_paint_pango_text(cr, &text_p, layout, buffer); } if (attractor_view->response[0][0][0] != -1) { for (c = 0; c < ATTRACTOR_LESION_LEVEL; c++) { for (p = 0; p < P; p++) { g_snprintf(buffer, 64, "%s", get_name_string(attractor_view->response[c][attractor_view->type][p])); cairox_text_parameters_set(&text_p, column_width*(c+1), (p+4)* row_height, PANGOX_XALIGN_LEFT, PANGOX_YALIGN_TOP, 0.0); cairox_paint_pango_text(cr, &text_p, layout, buffer); } } } g_object_unref(layout); cairo_destroy(cr); }
static gboolean _lib_navigation_draw_callback(GtkWidget *widget, cairo_t *crf, gpointer user_data) { dt_lib_module_t *self = (dt_lib_module_t *)user_data; dt_lib_navigation_t *d = (dt_lib_navigation_t *)self->data; const int inset = DT_NAVIGATION_INSET; GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int width = allocation.width, height = allocation.height; dt_develop_t *dev = darktable.develop; /* double buffering of image data: only take new data if valid */ if(dev->preview_pipe->backbuf && dev->preview_status == DT_DEV_PIXELPIPE_VALID) { /* re-allocate in case of changed image dimensions */ if(d->buffer == NULL || dev->preview_pipe->backbuf_width != d->wd || dev->preview_pipe->backbuf_height != d->ht) { g_free(d->buffer); d->wd = dev->preview_pipe->backbuf_width; d->ht = dev->preview_pipe->backbuf_height; d->buffer = g_malloc0((size_t)d->wd * d->ht * 4 * sizeof(unsigned char)); } /* update buffer if new data is available */ if(d->buffer && dev->preview_pipe->input_timestamp > d->timestamp) { dt_pthread_mutex_t *mutex = &dev->preview_pipe->backbuf_mutex; dt_pthread_mutex_lock(mutex); memcpy(d->buffer, dev->preview_pipe->backbuf, (size_t)d->wd * d->ht * 4 * sizeof(unsigned char)); d->timestamp = dev->preview_pipe->input_timestamp; dt_pthread_mutex_unlock(mutex); } } /* get the current style */ cairo_surface_t *cst = dt_cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cr = cairo_create(cst); GtkStyleContext *context = gtk_widget_get_style_context(widget); gtk_render_background(context, cr, 0, 0, allocation.width, allocation.height); width -= 2 * inset; height -= 2 * inset; cairo_translate(cr, inset, inset); /* draw navigation image if available */ if(d->buffer) { cairo_save(cr); const int wd = d->wd; const int ht = d->ht; const float scale = fminf(width / (float)wd, height / (float)ht); const int stride = cairo_format_stride_for_width(CAIRO_FORMAT_RGB24, wd); cairo_surface_t *surface = cairo_image_surface_create_for_data(d->buffer, CAIRO_FORMAT_RGB24, wd, ht, stride); cairo_translate(cr, width / 2.0, height / 2.0f); cairo_scale(cr, scale, scale); cairo_translate(cr, -.5f * wd, -.5f * ht); // draw shadow around float alpha = 1.0f; for(int k = 0; k < 4; k++) { cairo_rectangle(cr, -k / scale, -k / scale, wd + 2 * k / scale, ht + 2 * k / scale); cairo_set_source_rgba(cr, 0, 0, 0, alpha); alpha *= 0.6f; cairo_fill(cr); } cairo_rectangle(cr, 0, 0, wd - 2, ht - 1); cairo_set_source_surface(cr, surface, 0, 0); cairo_pattern_set_filter(cairo_get_source(cr), CAIRO_FILTER_FAST); cairo_fill(cr); cairo_surface_destroy(surface); // draw box where we are dt_dev_zoom_t zoom = dt_control_get_dev_zoom(); int closeup = dt_control_get_dev_closeup(); float zoom_x = dt_control_get_dev_zoom_x(); float zoom_y = dt_control_get_dev_zoom_y(); const float min_scale = dt_dev_get_zoom_scale(dev, DT_ZOOM_FIT, closeup ? 2.0 : 1.0, 0); const float cur_scale = dt_dev_get_zoom_scale(dev, zoom, closeup ? 2.0 : 1.0, 0); // avoid numerical instability for small resolutions: double h, w; if(cur_scale > min_scale) { float boxw = 1, boxh = 1; dt_dev_check_zoom_bounds(darktable.develop, &zoom_x, &zoom_y, zoom, closeup, &boxw, &boxh); cairo_translate(cr, wd * (.5f + zoom_x), ht * (.5f + zoom_y)); cairo_set_source_rgb(cr, 0., 0., 0.); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(1.f / scale)); boxw *= wd; boxh *= ht; cairo_rectangle(cr, -boxw / 2 - 1, -boxh / 2 - 1, boxw + 2, boxh + 2); cairo_stroke(cr); cairo_set_source_rgb(cr, 1., 1., 1.); cairo_rectangle(cr, -boxw / 2, -boxh / 2, boxw, boxh); cairo_stroke(cr); } cairo_restore(cr); if(fabsf(cur_scale - min_scale) > 0.001f) { /* Zoom % */ PangoLayout *layout; PangoRectangle ink; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); const float fontsize = DT_PIXEL_APPLY_DPI(11); pango_font_description_set_absolute_size(desc, fontsize * PANGO_SCALE); pango_layout_set_font_description(layout, desc); cairo_translate(cr, 0, height); cairo_set_source_rgba(cr, 1., 1., 1., 0.5); cairo_set_line_join(cr, CAIRO_LINE_JOIN_ROUND); char zoomline[5]; snprintf(zoomline, sizeof(zoomline), "%.0f%%", cur_scale * 100); pango_layout_set_text(layout, zoomline, -1); pango_layout_get_pixel_extents(layout, &ink, NULL); h = d->zoom_h = ink.height; w = d->zoom_w = ink.width; cairo_move_to(cr, width - w - h * 1.1 - ink.x, - fontsize); cairo_save(cr); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0)); GdkRGBA *color; gtk_style_context_get(context, gtk_widget_get_state_flags(widget), "background-color", &color, NULL); gdk_cairo_set_source_rgba(cr, color); pango_cairo_layout_path(cr, layout); cairo_stroke_preserve(cr); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_fill(cr); cairo_restore(cr); gdk_rgba_free(color); pango_font_description_free(desc); g_object_unref(layout); } else { // draw the zoom-to-fit icon cairo_translate(cr, 0, height); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); static int height = -1; if(height == -1) { PangoLayout *layout; PangoRectangle ink; PangoFontDescription *desc = pango_font_description_copy_static(darktable.bauhaus->pango_font_desc); pango_font_description_set_weight(desc, PANGO_WEIGHT_BOLD); layout = pango_cairo_create_layout(cr); pango_font_description_set_absolute_size(desc, DT_PIXEL_APPLY_DPI(11) * PANGO_SCALE); pango_layout_set_font_description(layout, desc); pango_layout_set_text(layout, "100%", -1); // dummy text, just to get the height pango_layout_get_pixel_extents(layout, &ink, NULL); height = ink.height; pango_font_description_free(desc); g_object_unref(layout); } h = d->zoom_h = height; w = h * 1.5; float sp = h * 0.6; d->zoom_w = w + sp; cairo_move_to(cr, width - w - h - sp, -1.0 * h); cairo_rectangle(cr, width - w - h - sp, -1.0 * h, w, h); cairo_set_source_rgb(cr, 0.2, 0.2, 0.2); cairo_fill(cr); cairo_set_line_width(cr, DT_PIXEL_APPLY_DPI(2.0)); cairo_set_source_rgb(cr, 0.6, 0.6, 0.6); cairo_move_to(cr, width - w * 0.8 - h - sp, -1.0 * h); cairo_line_to(cr, width - w - h - sp, -1.0 * h); cairo_line_to(cr, width - w - h - sp, -0.7 * h); cairo_stroke(cr); cairo_move_to(cr, width - w - h - sp, -0.3 * h); cairo_line_to(cr, width - w - h - sp, 0); cairo_line_to(cr, width - w * 0.8 - h - sp, 0); cairo_stroke(cr); cairo_move_to(cr, width - w * 0.2 - h - sp, 0); cairo_line_to(cr, width - h - sp, 0); cairo_line_to(cr, width - h - sp, -0.3 * h); cairo_stroke(cr); cairo_move_to(cr, width - h - sp, -0.7 * h); cairo_line_to(cr, width - h - sp, -1.0 * h); cairo_line_to(cr, width - w * 0.2 - h - sp, -1.0 * h); cairo_stroke(cr); } cairo_move_to(cr, width - 0.95 * h, -0.9 * h); cairo_line_to(cr, width - 0.05 * h, -0.9 * h); cairo_line_to(cr, width - 0.5 * h, -0.1 * h); cairo_fill(cr); } /* blit memsurface into widget */ cairo_destroy(cr); cairo_set_source_surface(crf, cst, 0, 0); cairo_paint(crf); cairo_surface_destroy(cst); return TRUE; }
static gboolean _tristatebutton_expose(GtkWidget *widget, GdkEventExpose *event) { g_return_val_if_fail(widget != NULL, FALSE); g_return_val_if_fail(DTGTK_IS_TRISTATEBUTTON(widget), FALSE); g_return_val_if_fail(event != NULL, FALSE); GtkStyle *style = gtk_widget_get_style(widget); int state = gtk_widget_get_state(widget); /* fix text style */ for(int i = 0; i < 5; i++) style->text[i] = style->fg[i]; /* fetch flags */ int flags = DTGTK_TRISTATEBUTTON(widget)->icon_flags; /* set inner border */ int border = DT_PIXEL_APPLY_DPI((flags & CPF_DO_NOT_USE_BORDER) ? 2 : 6); /* update active state paint flag */ gboolean active = DTGTK_TRISTATEBUTTON(widget)->state > 0; if(active) flags |= CPF_ACTIVE; else flags &= ~(CPF_ACTIVE); /* begin cairo drawing */ cairo_t *cr; cr = gdk_cairo_create(gtk_widget_get_window(widget)); GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int x = allocation.x; int y = allocation.y; int width = allocation.width; int height = allocation.height; /* draw standard button background if not transparent nor flat styled */ if((flags & CPF_STYLE_FLAT)) { if(state != GTK_STATE_NORMAL) { cairo_rectangle(cr, x, y, width, height); cairo_set_source_rgba(cr, style->bg[state].red / 65535.0, style->bg[state].green / 65535.0, style->bg[state].blue / 65535.0, 0.5); cairo_fill(cr); } } else if(!(flags & CPF_BG_TRANSPARENT)) { cairo_rectangle(cr, x, y, width, height); float rs = 1.0, gs = 1.0, bs = 1.0; if(DTGTK_TRISTATEBUTTON(widget)->state == 1) rs = gs = bs = 3.0; else if(DTGTK_TRISTATEBUTTON(widget)->state == 2) rs = 3.0; cairo_set_source_rgba(cr, (style->bg[state].red / 65535.0) * rs, (style->bg[state].green / 65535.0) * gs, (style->bg[state].blue / 65535.0) * bs, 0.5); cairo_fill(cr); } /* create pango text settings if label exists */ PangoLayout *layout = NULL; int pw = 0, ph = 0; const gchar *text = gtk_button_get_label(GTK_BUTTON(widget)); if(text) { layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, darktable.bauhaus->pango_font_desc); pango_cairo_context_set_resolution(pango_layout_get_context(layout), darktable.gui->dpi); pango_layout_set_text(layout, text, -1); pango_layout_get_pixel_size(layout, &pw, &ph); } cairo_set_source_rgb(cr, style->fg[state].red / 65535.0, style->fg[state].green / 65535.0, style->fg[state].blue / 65535.0); /* draw button image if any */ GtkWidget *image = gtk_button_get_image(GTK_BUTTON(widget)); if(image) { GdkPixbuf *pixbuf = gtk_image_get_pixbuf(GTK_IMAGE(image)); if(pixbuf) { /* Draw the pixbuf */ gint pbw = gdk_pixbuf_get_width(pixbuf); gint pbh = gdk_pixbuf_get_height(pixbuf); gdk_cairo_set_source_pixbuf(cr, pixbuf, allocation.x + ((allocation.width / 2) - (pbw / 2)), allocation.y + ((allocation.height / 2) - (pbh / 2))); cairo_paint(cr); } } /* draw icon */ if(DTGTK_TRISTATEBUTTON(widget)->icon) { // if (flags & CPF_IGNORE_FG_STATE) // state = GTK_STATE_NORMAL; if(text) DTGTK_TRISTATEBUTTON(widget) ->icon(cr, x + border, y + border, height - (border * 2), height - (border * 2), flags); else DTGTK_TRISTATEBUTTON(widget) ->icon(cr, x + border, y + border, width - (border * 2), height - (border * 2), flags); } /* draw label */ if(text) { int lx = x + DT_PIXEL_APPLY_DPI(2), ly = y + ((height / 2.0) - (ph / 2.0)); cairo_translate(cr, lx, ly); pango_cairo_show_layout(cr, layout); g_object_unref(layout); } cairo_destroy(cr); return FALSE; }
static gboolean _togglebutton_expose(GtkWidget *widget, GdkEventExpose *event) { g_return_val_if_fail (widget != NULL, FALSE); g_return_val_if_fail (DTGTK_IS_TOGGLEBUTTON(widget), FALSE); g_return_val_if_fail (event != NULL, FALSE); GtkStyle *style=gtk_widget_get_style(widget); int state = gtk_widget_get_state(widget); /* fix text style */ for(int i=0; i<5; i++) style->text[i]=style->fg[i]; /* fetch flags */ int flags = DTGTK_TOGGLEBUTTON (widget)->icon_flags; /* set inner border */ int border = (flags&CPF_DO_NOT_USE_BORDER)?2:6; /* update active state paint flag */ gboolean active = gtk_toggle_button_get_active ( GTK_TOGGLE_BUTTON (widget)); if (active) flags |= CPF_ACTIVE; else flags &=~(CPF_ACTIVE); /* prelight */ if (state == GTK_STATE_PRELIGHT) flags |= CPF_PRELIGHT; else flags &=~CPF_PRELIGHT; /* begin cairo drawing */ cairo_t *cr; cr = gdk_cairo_create (gtk_widget_get_window(widget)); GtkAllocation allocation; gtk_widget_get_allocation(widget, &allocation); int x = allocation.x; int y = allocation.y; int width = allocation.width; int height = allocation.height; /* draw standard button background if not transparent nor flat styled */ if( (flags & CPF_STYLE_FLAT )) { if( state != GTK_STATE_NORMAL ) { cairo_rectangle (cr,x,y,width,height); cairo_set_source_rgba (cr, style->bg[state].red/65535.0, style->bg[state].green/65535.0, style->bg[state].blue/65535.0, 0.5); cairo_fill (cr); } } else if( !(flags & CPF_BG_TRANSPARENT) ) { /* draw default boxed button */ gtk_paint_box (gtk_widget_get_style(widget), gtk_widget_get_window(widget), gtk_widget_get_state(widget), GTK_SHADOW_OUT, NULL, widget, "button", x, y, width, height); } /* create pango text settings if label exists */ PangoLayout *layout=NULL; int pw=0,ph=0; const gchar *text=gtk_button_get_label (GTK_BUTTON (widget)); if (text) { layout = pango_cairo_create_layout (cr); pango_layout_set_font_description (layout,style->font_desc); pango_layout_set_text (layout,text,-1); pango_layout_get_pixel_size (layout,&pw,&ph); } cairo_set_source_rgb (cr, style->fg[state].red/65535.0, style->fg[state].green/65535.0, style->fg[state].blue/65535.0); /* draw icon */ if (DTGTK_TOGGLEBUTTON (widget)->icon) { // if (flags & CPF_IGNORE_FG_STATE) // state = GTK_STATE_NORMAL; if (text) DTGTK_TOGGLEBUTTON (widget)->icon (cr,x+border,y+border,height-(border*2),height-(border*2),flags); else DTGTK_TOGGLEBUTTON (widget)->icon (cr,x+border,y+border,width-(border*2),height-(border*2),flags); } /* draw label */ if (text) { int lx=x+2, ly=y+((height/2.0)-(ph/2.0)); //if (DTGTK_TOGGLEBUTTON (widget)->icon) lx += width; //GdkRectangle t={x,y,x+width,y+height}; //gtk_paint_layout(style,gtk_widget_get_window(widget), state,TRUE,&t,widget,"togglebutton",lx,ly,layout); cairo_translate(cr, lx, ly); pango_cairo_show_layout (cr,layout); } cairo_destroy (cr); return FALSE; }
/* Info */ static void info_expose(GritsCallback *compass, GritsOpenGL *opengl, gpointer _env) { GtkAllocation alloc; gtk_widget_get_allocation(GTK_WIDGET(opengl), &alloc); /* Create cairo surface */ guint tex = 0; const gchar *label0 = "Location: %7.3lf°, %8.3lf°, %4.0fm"; const gchar *label1 = "Cursor: %7.3lf°, %8.3lf°, %4.0fm"; gdouble width = 300; gdouble height = 200; cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); cairo_t *cairo = cairo_create(surface); /* Text */ gdouble lat, lon, elev; grits_viewer_get_location(GRITS_VIEWER(opengl), &lat, &lon, &elev); gchar *text0 = g_strdup_printf(label0, lat, lon, elev); gchar *text1 = g_strdup_printf(label1, lat, lon, elev); /* Draw outline */ cairo_set_line_width(cairo, 3); cairo_set_source_rgba(cairo, 0, 0, 0, 0.75); cairo_move_to(cairo, 2, 20); cairo_text_path(cairo, text0); cairo_move_to(cairo, 2, 40); cairo_text_path(cairo, text1); cairo_stroke(cairo); /* Draw filler */ cairo_set_source_rgba(cairo, 1, 1, 1, 1); cairo_move_to(cairo, 2, 20); cairo_show_text(cairo, text0); cairo_move_to(cairo, 2, 40); cairo_show_text(cairo, text1); /* Setup pango */ PangoLayout *layout = pango_cairo_create_layout(cairo); PangoFontDescription *font = pango_font_description_from_string("Mono 9"); pango_layout_set_font_description(layout, font); pango_font_description_free(font); pango_layout_set_text(layout, text0, -1); pango_cairo_update_layout(cairo, layout); cairo_set_line_join(cairo, CAIRO_LINE_JOIN_ROUND); cairo_move_to(cairo, 2, 40); pango_cairo_layout_path(cairo, layout); for (float w = 0.2; w <= 0.8; w+=0.2) { cairo_set_line_width(cairo, (1-w)*8); cairo_set_source_rgba(cairo, 0, 0, 0, w); cairo_stroke_preserve(cairo); } cairo_set_source_rgba(cairo, 1, 1, 1, 1); pango_cairo_show_layout(cairo, layout); /* Load GL texture */ glEnable(GL_TEXTURE_2D); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glPixelStorei(GL_PACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, 4, width, height, 0, GL_BGRA, GL_UNSIGNED_BYTE, cairo_image_surface_get_data(surface)); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); /* Draw surface */ glDisable(GL_LIGHTING); glDisable(GL_COLOR_MATERIAL); glDisable(GL_DEPTH_TEST); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, tex); glDisable(GL_CULL_FACE); glTranslatef(alloc.width - width, alloc.height - height, 0); glBegin(GL_QUADS); glTexCoord2f(1, 0); glVertex3f(width, 0 , 0); // 0 - 3 0 glTexCoord2f(1, 1); glVertex3f(width, height, 0); // 1 - | | glTexCoord2f(0, 1); glVertex3f(0 , height, 0); // 2 - | | glTexCoord2f(0, 0); glVertex3f(0 , 0 , 0); // 3 - 2----1 glEnd(); }
cairo_surface_t* render_text_to_surface (gchar* text, gint width, gint height, const cairo_font_options_t* font_opts, gdouble dpi) { cairo_surface_t* surface; cairo_t* cr; PangoFontDescription* desc; PangoLayout* layout; // sanity check if (!text || width <= 0 || height <= 0) return NULL; // create surface surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height); if (cairo_surface_status (surface) != CAIRO_STATUS_SUCCESS) return NULL; // create context cr = cairo_create (surface); if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) { cairo_surface_destroy (surface); return NULL; } // clear context cairo_scale (cr, 1.0f, 1.0f); cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); cairo_paint (cr); // layout = pango_cairo_create_layout (cr); desc = pango_font_description_new (); pango_font_description_set_size (desc, 12 * PANGO_SCALE); pango_font_description_set_family_static (desc, "Candara"); pango_font_description_set_weight (desc, PANGO_WEIGHT_NORMAL); pango_font_description_set_style (desc, PANGO_STYLE_NORMAL); pango_layout_set_wrap (layout, PANGO_WRAP_WORD); pango_layout_set_font_description (layout, desc); pango_font_description_free (desc); pango_layout_set_width (layout, width * PANGO_SCALE); pango_layout_set_height (layout, height * PANGO_SCALE); pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); // print and layout string (pango-wise) pango_layout_set_text (layout, text, -1); // make sure system-wide font-options like hinting, antialiasing etc. // are taken into account pango_cairo_context_set_font_options (pango_layout_get_context (layout), font_opts); pango_cairo_context_set_resolution (pango_layout_get_context (layout), dpi); pango_layout_context_changed (layout); // draw pango-text to our cairo-context cairo_move_to (cr, 0.0f, 0.0f); cairo_set_operator (cr, CAIRO_OPERATOR_OVER); cairo_set_source_rgba (cr, 1.0f, 1.0f, 1.0f, 1.0f); // this call leaks 3803 bytes, I've no idea how to fix that pango_cairo_show_layout (cr, layout); // clean up g_object_unref (layout); cairo_destroy (cr); return surface; }
/** * ppg_ruler_draw_ruler: * @ruler: (in): A #PpgRuler. * * Draws the background of the ruler containing the time values and ticks * to an offscreen pixmap that can be blitted to the widget during * "expose-event". * * Returns: None. * Side effects: None. */ static void ppg_ruler_draw_ruler (PpgRuler *ruler) { PpgRulerPrivate *priv; GtkAllocation alloc; PangoLayout *layout; cairo_t *cr; GtkStyle *style; GdkColor text_color; gint text_width; gint text_height; gdouble every = 1.0; gdouble n_seconds; gdouble v; gdouble p; gint pw; gint ph; gint x; gint xx; gint n; gint z = 0; g_return_if_fail(PPG_IS_RULER(ruler)); priv = ruler->priv; gtk_widget_get_allocation(GTK_WIDGET(ruler), &alloc); style = gtk_widget_get_style(GTK_WIDGET(ruler)); cr = cairo_create(priv->ruler); cairo_save(cr); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_rectangle(cr, 0, 0, alloc.width, alloc.height); cairo_fill(cr); cairo_restore(cr); text_color = style->text[GTK_STATE_NORMAL]; cairo_set_line_width(cr, 1.0); gdk_cairo_set_source_color(cr, &text_color); layout = pango_cairo_create_layout(cr); pango_layout_set_font_description(layout, priv->font_desc); pango_layout_set_markup(layout, "00:00:00.000", -1); pango_layout_get_pixel_size(layout, &text_width, &text_height); text_width += 5; n_seconds = priv->upper - priv->lower; if ((alloc.width / n_seconds) < text_width) { every = ceil(text_width / (alloc.width / n_seconds)); } for (v = floor(priv->lower); v < priv->upper; v += every) { gdk_cairo_set_source_color(cr, &text_color); x = get_x_offset(priv, &alloc, v); cairo_move_to(cr, x + 0.5, alloc.height - 1.5); cairo_line_to(cr, x + 0.5, 0.5); /* * Mini lines. */ for (p = v, n = 0, z = 0; p < v + every; p += (every / 10), n++, z++) { if (n == 0 || n == 10) { continue; } xx = get_x_offset(priv, &alloc, p); cairo_move_to(cr, xx + 0.5, alloc.height - 1.5); if (z % 2 == 0) { cairo_line_to(cr, xx + 0.5, text_height + 8.5); } else { cairo_line_to(cr, xx + 0.5, text_height + 5.5); } } cairo_stroke(cr); cairo_move_to(cr, x + 1.5, 1.5); ppg_ruler_update_layout_text(ruler, layout, CLAMP(v, priv->lower, priv->upper)); /* * If there is enough room to draw this layout before we get to the * next layout, then draw it. */ pango_layout_get_pixel_size(layout, &pw, &ph); if ((x + pw) < get_x_offset(priv, &alloc, floor(v) + every)) { pango_cairo_show_layout(cr, layout); } } g_object_unref(layout); cairo_destroy(cr); }
static void conting_cs_draw(ContingDrawing *self, cairo_t *cr) { ContingSymbol *symb; ContingComponent *comp; GdkColor *color; ArtPoint pw0, pw1; GdkRectangle rect; gdouble affine[6]; g_return_if_fail(self != NULL && CONTING_IS_CS(self)); symb = CONTING_SYMBOL(self); comp = CONTING_COMPONENT(self); g_object_get(self, "color", &color, NULL); pw0 = comp->p0; pw1 = comp->p1; rect.x = (pw0.x < pw1.x ? pw0.x : pw1.x); rect.y = (pw0.y < pw1.y ? pw0.y : pw1.y); rect.width = fabs(pw1.x - pw0.x); rect.height = fabs(pw1.y - pw0.y); cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT); cairo_arc(cr, rect.x + ((gdouble) rect.width / 2.0), rect.y + ((gdouble) rect.height / 2.0), (gdouble) rect.width / 2.0, 0, 2 * M_PI); cairo_set_source_rgb(cr, (gdouble) color->red / (gdouble) G_MAXUINT16, (gdouble) color->green / (gdouble) G_MAXUINT16, (gdouble) color->blue / (gdouble) G_MAXUINT16); cairo_stroke(cr); cr = conting_drawing_get_cairo_absolute(self); conting_drawing_get_i2w_affine_absolute(self, affine); cairo_transform(cr, (cairo_matrix_t *) affine); cairo_set_antialias(cr, CAIRO_ANTIALIAS_DEFAULT); cairo_set_source_rgb(cr, (gdouble) color->red / (gdouble) G_MAXUINT16, (gdouble) color->green / (gdouble) G_MAXUINT16, (gdouble) color->blue / (gdouble) G_MAXUINT16); { PangoLayout *layout; PangoFontDescription *font; layout = pango_cairo_create_layout(cr); font = pango_font_description_new(); pango_font_description_set_size(font, 4 * PANGO_SCALE); /* g_print("size = %d\n", pango_font_description_get_size(font)); */ pango_font_description_set_family_static(font, "Arial"); pango_font_description_set_style(font, PANGO_STYLE_NORMAL); pango_layout_set_font_description(layout, font); pango_layout_set_text(layout, "CS", 2); cairo_move_to(cr, pw0.x + 1, pw0.y + 2); pango_cairo_update_layout(cr, layout); pango_cairo_show_layout(cr, layout); g_object_unref(layout); } cairo_stroke(cr); cairo_destroy(cr); CONTING_DRAWING_CLASS(parent_class)->draw(self, cr); }
static void draw_str(struct gra2cairo_local *local, int draw, char *str, struct fontmap *font, int size, int space, int *fw, int *ah, int *dh) { PangoAttribute *attr; PangoAttrList *alist; PangoLayoutIter *piter; int w, h, baseline; if (size == 0 || str == NULL) { if (fw) *fw = 0; if (ah) *ah = 0; if (dh) *dh = 0; return; } if (local->layout == NULL) { local->layout = pango_cairo_create_layout(local->cairo); } alist = pango_attr_list_new(); attr = pango_attr_size_new_absolute(mxd2ph(local, size) * PANGO_SCALE); pango_attr_list_insert(alist, attr); attr = pango_attr_letter_spacing_new(mxd2ph(local, space) * PANGO_SCALE); pango_attr_list_insert(alist, attr); pango_layout_set_font_description(local->layout, font->font); pango_layout_set_attributes(local->layout, alist); pango_attr_list_unref(alist); pango_layout_set_text(local->layout, str, -1); pango_layout_get_pixel_size(local->layout, &w, &h); piter = pango_layout_get_iter(local->layout); baseline = pango_layout_iter_get_baseline(piter) / PANGO_SCALE; if (fw) *fw = w; if (ah) *ah = baseline; if (dh) *dh = h - baseline; if (draw && str) { double x, y; double cx, cy; x = - local->fontsin * baseline; y = - local->fontcos * baseline; cairo_get_current_point(local->cairo, &cx, &cy); relative_move(local->cairo, x, y); cairo_save(local->cairo); cairo_rotate(local->cairo, -local->fontdir * G_PI / 180.); pango_cairo_update_layout(local->cairo, local->layout); if (local->text2path) { pango_cairo_layout_path(local->cairo, local->layout); cairo_fill(local->cairo); cairo_restore(local->cairo); cairo_move_to(local->cairo, cx + w * local->fontcos, cy - w * local->fontsin); } else { pango_cairo_show_layout(local->cairo, local->layout); cairo_restore(local->cairo); relative_move(local->cairo, w * local->fontcos - x, - w * local->fontsin - y); } } pango_layout_iter_free(piter); }
void render_glyph( cairo_t* cr, PangoFontDescription* font_desc, PangoFont* font, const guint code_point, const size_t cell_x, const size_t cell_y, const size_t cell_size, const double tex_size, const int ascent, const int descent, std::ostream& bgm_out ) { PangoLayout *layout = pango_cairo_create_layout(cr); char str[6] = {'\0'}; size_t len = 0; oglplus::aux::ConvertCodePointToUTF8(code_point, str, len); pango_layout_set_font_description(layout, font_desc); pango_layout_set_text(layout, str, len); const int baseline = pango_layout_get_baseline(layout); const double inv_ps = 1.0 / double(PANGO_SCALE); const double font_size = ascent+descent; PangoRectangle ink_rect, log_rect; pango_layout_get_extents( layout, &ink_rect, &log_rect ); // code point number bgm_out << code_point << std::endl; // hex representation of the number bgm_out << std::hex << "0x" << code_point << std::dec << std::endl; // the utf-8 sequence bgm_out << "'" << str << "'" << std::endl; // // vertex[0] logical rectangle metrics // // Left bearing (x) bgm_out << PANGO_LBEARING(log_rect)/font_size << std::endl; // Right bearing (x+width) bgm_out << PANGO_RBEARING(log_rect)/font_size << std::endl; // Ascent bgm_out << (baseline-log_rect.y)/font_size << std::endl; // Descent bgm_out << (log_rect.height+log_rect.y-baseline)/font_size << std::endl; // // vertex[1] ink rectangle metrics // // Left bearing (x) bgm_out << PANGO_LBEARING(ink_rect)/font_size << std::endl; // Right bearing (x+width) bgm_out << PANGO_RBEARING(ink_rect)/font_size << std::endl; // Ascent bgm_out << (baseline-ink_rect.y)/font_size << std::endl; // Descent bgm_out << (ink_rect.y+ink_rect.height-baseline)/font_size << std::endl; // // vertex[2] texture coordinates // // Origin X bgm_out << (cell_x*cell_size+ink_rect.x*inv_ps)/tex_size << std::endl; // Origin Y bgm_out << 1.0-(cell_y*cell_size+baseline*inv_ps)/tex_size << std::endl; // Width bgm_out << ((ink_rect.width)*inv_ps)/tex_size << std::endl; // Height bgm_out << ((ink_rect.height)*inv_ps)/tex_size << std::endl; // separating newline bgm_out << std::endl; cairo_new_path(cr); cairo_move_to(cr, cell_x*cell_size, cell_y*cell_size); cairo_set_line_width(cr, 0.5); pango_cairo_update_layout(cr, layout); pango_cairo_layout_path(cr, layout); cairo_fill(cr); g_object_unref(layout); }
static void hb_pdf_draw_line(PdfPrintContext *ppc, cairo_t *cr, gdouble y, gboolean bold, gboolean rulehint) { PangoLayout *layout; gint i; gdouble x; /* Create a PangoLayout, set the font and text */ layout = pango_cairo_create_layout (cr); //desc = pango_font_description_from_string (FONT); if(bold) pango_font_description_set_weight(ppc->desc, PANGO_WEIGHT_BOLD); else pango_font_description_set_weight(ppc->desc, PANGO_WEIGHT_NORMAL); pango_layout_set_font_description (layout, ppc->desc); x = ppc->ml; /* rule hint */ #if RULEHINT == 1 if( rulehint ) { cairo_set_source_rgb(cr, 0.9, 0.9, 0.9); cairo_rectangle (cr, x, y, ppc->w - ppc->ml - ppc->mr, PDF_FONT_NORMAL); cairo_fill(cr); } #endif cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); cairo_move_to(cr, x, y); for(i=0;i<PDF_NUMCOL;i++) { if(ppc->column_txt[i] != NULL) { int width, height; pango_layout_set_text (layout, ppc->column_txt[i], -1); pango_layout_get_size (layout, &width, &height); if( i==1 || i==2 || i==3 ) { pango_layout_set_width(layout, ppc->column_width[i]*PANGO_SCALE); pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); } //cairo_set_source_rgb(cr, 0.0, 0.0, 0.0); if( i==0 || i==4 || i==6 ) // pad right: date/amount/balance { //if(*ppc->column_txt[i] != '-') //cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.66); //grey cairo_move_to(cr, x + ppc->column_width[i] - (width/PANGO_SCALE) , y); } else cairo_move_to(cr, x, y); pango_cairo_show_layout (cr, layout); /* test line */ /*cairo_set_line_width(cr, 1.0); cairo_move_to(cr, x, y + .5); cairo_line_to(cr, x + ppc->column_width[i], y+.5); cairo_stroke(cr); */ } x += ppc->column_width[i] + PDF_COL_MARGIN; } g_object_unref (layout); }