1/* 2 * Copyright 2019 Michael Gratton <mike@vee.net> 3 * 4 * This software is licensed under the GNU Lesser General Public License 5 * (version 2.1 or later). See the COPYING file in this distribution. 6 */ 7 8namespace Util.Avatar { 9 10 // The following was based on code written by Felipe Borges for 11 // gnome-control-enter in panels/user-accounts/user-utils.c commit 12 // 02c288ab6f069a0c106323a93400f192a63cb67e. The copyright in that 13 // file is: "Copyright 2009-2010 Red Hat, Inc," 14 15 public Gdk.Pixbuf generate_user_picture(string name, int size) { 16 Cairo.Surface surface = new Cairo.ImageSurface( 17 Cairo.Format.ARGB32, size, size 18 ); 19 Cairo.Context cr = new Cairo.Context(surface); 20 cr.rectangle(0, 0, size, size); 21 22 /* Fill the background with a colour for the name */ 23 Gdk.RGBA color = get_color_for_name(name); 24 cr.set_source_rgb( 25 color.red / 255.0, color.green / 255.0, color.blue / 255.0 26 ); 27 cr.fill(); 28 29 /* Draw the initials on top */ 30 string? initials = extract_initials_from_name(name); 31 if (initials != null) { 32 string font = "Sans %d".printf((int) GLib.Math.ceil(size / 2.5)); 33 34 cr.set_source_rgb(1.0, 1.0, 1.0); 35 Pango.Layout layout = Pango.cairo_create_layout(cr); 36 layout.set_text(initials, -1); 37 layout.set_font_description(Pango.FontDescription.from_string(font)); 38 39 int width, height; 40 layout.get_size(out width, out height); 41 cr.translate(size / 2, size / 2); 42 cr.move_to( 43 -((double) width / Pango.SCALE) / 2, 44 -((double) height / Pango.SCALE) / 2 45 ); 46 Pango.cairo_show_layout(cr, layout); 47 } 48 49 return Gdk.pixbuf_get_from_surface( 50 surface, 0, 0, size, size 51 ); 52 } 53 54 public Gdk.Pixbuf round_image(Gdk.Pixbuf source) { 55 int size = source.width; 56 Cairo.Surface surface = new Cairo.ImageSurface( 57 Cairo.Format.ARGB32, size, size 58 ); 59 Cairo.Context cr = new Cairo.Context(surface); 60 61 /* Clip a circle */ 62 cr.arc(size / 2, size / 2, size / 2, 0, 2 * GLib.Math.PI); 63 cr.clip(); 64 cr.new_path(); 65 66 Gdk.cairo_set_source_pixbuf(cr, source, 0, 0); 67 cr.paint(); 68 69 return Gdk.pixbuf_get_from_surface( 70 surface, 0, 0, size, size 71 ); 72 } 73 74 public string? extract_initials_from_name(string name) { 75 string normalized = name.strip().normalize(-1, DEFAULT_COMPOSE); 76 string? initials = null; 77 if (normalized != "") { 78 GLib.StringBuilder buf = new GLib.StringBuilder(); 79 unichar c = 0; 80 int index = 0; 81 82 // Get the first alphanumeric char of the string 83 for (int i = 0; normalized.get_next_char(ref index, out c); i++) { 84 if (c.isalnum()) { 85 buf.append_unichar(c.toupper()); 86 break; 87 } 88 } 89 90 // Get the first alphanumeric char of the last word of the string 91 index = normalized.last_index_of_char(' '); 92 if (index >= 0) { 93 for (int i = 0; normalized.get_next_char(ref index, out c); i++) { 94 if (c.isalnum()) { 95 buf.append_unichar(c.toupper()); 96 break; 97 } 98 } 99 } 100 101 if (buf.data.length > 0) { 102 initials = (string) buf.data; 103 } 104 } 105 return initials; 106 } 107 108 109 public Gdk.RGBA get_color_for_name(string name) { 110 // https://gitlab.gnome.org/Community/Design/HIG-app-icons/blob/master/GNOME%20HIG.gpl 111 const double[,] GNOME_COLOR_PALETTE = { 112 { 98, 160, 234 }, 113 { 53, 132, 228 }, 114 { 28, 113, 216 }, 115 { 26, 95, 180 }, 116 { 87, 227, 137 }, 117 { 51, 209, 122 }, 118 { 46, 194, 126 }, 119 { 38, 162, 105 }, 120 { 248, 228, 92 }, 121 { 246, 211, 45 }, 122 { 245, 194, 17 }, 123 { 229, 165, 10 }, 124 { 255, 163, 72 }, 125 { 255, 120, 0 }, 126 { 230, 97, 0 }, 127 { 198, 70, 0 }, 128 { 237, 51, 59 }, 129 { 224, 27, 36 }, 130 { 192, 28, 40 }, 131 { 165, 29, 45 }, 132 { 192, 97, 203 }, 133 { 163, 71, 186 }, 134 { 129, 61, 156 }, 135 { 97, 53, 131 }, 136 { 181, 131, 90 }, 137 { 152, 106, 68 }, 138 { 134, 94, 60 }, 139 { 99, 69, 44 } 140 }; 141 142 Gdk.RGBA color = { 255, 255, 255, 1.0 }; 143 uint hash; 144 uint number_of_colors; 145 uint idx; 146 147 if (name == "") { 148 return color; 149 } 150 151 hash = name.hash(); 152 number_of_colors = GNOME_COLOR_PALETTE.length[0]; 153 idx = hash % number_of_colors; 154 155 color.red = GNOME_COLOR_PALETTE[idx,0]; 156 color.green = GNOME_COLOR_PALETTE[idx,1]; 157 color.blue = GNOME_COLOR_PALETTE[idx,2]; 158 159 return color; 160 } 161 162} 163