| 138 #define DEFAULT_HIGHLIGHT_COLOR "#AF7F00" |
138 #define DEFAULT_HIGHLIGHT_COLOR "#AF7F00" |
| 139 |
139 |
| 140 #define BUDDYICON_SIZE_MIN 32 |
140 #define BUDDYICON_SIZE_MIN 32 |
| 141 #define BUDDYICON_SIZE_MAX 96 |
141 #define BUDDYICON_SIZE_MAX 96 |
| 142 |
142 |
| 143 #define LUMINANCE(c) (float)((0.3*(c.red))+(0.59*(c.green))+(0.11*(c.blue))) |
|
| 144 |
|
| 145 #define MIN_LUMINANCE_CONTRAST_RATIO 4.5 |
143 #define MIN_LUMINANCE_CONTRAST_RATIO 4.5 |
| 146 |
144 |
| 147 #define NICK_COLOR_GENERATE_COUNT 220 |
145 #define NICK_COLOR_GENERATE_COUNT 220 |
| 148 static GArray *generated_nick_colors = NULL; |
146 static GArray *generated_nick_colors = NULL; |
| 149 |
147 |
| 202 static void conv_set_unseen(PurpleConversation *gtkconv, PidginUnseenState state); |
200 static void conv_set_unseen(PurpleConversation *gtkconv, PidginUnseenState state); |
| 203 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state); |
201 static void gtkconv_set_unseen(PidginConversation *gtkconv, PidginUnseenState state); |
| 204 static void update_typing_icon(PidginConversation *gtkconv); |
202 static void update_typing_icon(PidginConversation *gtkconv); |
| 205 static void update_typing_message(PidginConversation *gtkconv, const char *message); |
203 static void update_typing_message(PidginConversation *gtkconv, const char *message); |
| 206 gboolean pidgin_conv_has_focus(PurpleConversation *conv); |
204 gboolean pidgin_conv_has_focus(PurpleConversation *conv); |
| 207 static GArray* generate_nick_colors(guint numcolors, GdkColor background); |
205 static GArray* generate_nick_colors(guint numcolors, GdkRGBA background); |
| 208 gfloat luminance(GdkColor color); |
206 gfloat luminance(GdkRGBA color); |
| 209 static gboolean color_is_visible(GdkColor foreground, GdkColor background, gfloat min_contrast_ratio); |
207 static gboolean color_is_visible(GdkRGBA foreground, GdkRGBA background, gfloat min_contrast_ratio); |
| 210 static GtkTextTag *get_buddy_tag(PurpleChatConversation *chat, const char *who, PurpleMessageFlags flag, gboolean create); |
208 static GtkTextTag *get_buddy_tag(PurpleChatConversation *chat, const char *who, PurpleMessageFlags flag, gboolean create); |
| 211 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); |
209 static void pidgin_conv_update_fields(PurpleConversation *conv, PidginConvFields fields); |
| 212 static void focus_out_from_menubar(GtkWidget *wid, PidginConvWindow *win); |
210 static void focus_out_from_menubar(GtkWidget *wid, PidginConvWindow *win); |
| 213 static void pidgin_conv_tab_pack(PidginConvWindow *win, PidginConversation *gtkconv); |
211 static void pidgin_conv_tab_pack(PidginConvWindow *win, PidginConversation *gtkconv); |
| 214 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); |
212 static gboolean infopane_press_cb(GtkWidget *widget, GdkEventButton *e, PidginConversation *conv); |
| 216 |
214 |
| 217 static void pidgin_conv_set_position_size(PidginConvWindow *win, int x, int y, |
215 static void pidgin_conv_set_position_size(PidginConvWindow *win, int x, int y, |
| 218 int width, int height); |
216 int width, int height); |
| 219 static gboolean pidgin_conv_xy_to_right_infopane(PidginConvWindow *win, int x, int y); |
217 static gboolean pidgin_conv_xy_to_right_infopane(PidginConvWindow *win, int x, int y); |
| 220 |
218 |
| 221 static const GdkColor * |
219 static const GdkRGBA * |
| 222 get_nick_color(PidginConversation *gtkconv, const gchar *name) |
220 get_nick_color(PidginConversation *gtkconv, const gchar *name) |
| 223 { |
221 { |
| 224 static GdkColor col; |
222 static GdkRGBA col; |
| 225 |
223 |
| 226 if (name == NULL) { |
224 if (name == NULL) { |
| 227 col.red = col.green = col.blue = 0; |
225 col.red = col.green = col.blue = 0; |
| |
226 col.alpha = 1; |
| 228 return &col; |
227 return &col; |
| 229 } |
228 } |
| 230 |
229 |
| 231 col = g_array_index(gtkconv->nick_colors, GdkColor, |
230 col = g_array_index(gtkconv->nick_colors, GdkRGBA, |
| 232 g_str_hash(name) % gtkconv->nick_colors->len); |
231 g_str_hash(name) % gtkconv->nick_colors->len); |
| 233 |
232 |
| 234 return &col; |
233 return &col; |
| 235 } |
234 } |
| 236 |
235 |
| 4293 gboolean is_me = FALSE; |
4292 gboolean is_me = FALSE; |
| 4294 gboolean is_buddy; |
4293 gboolean is_buddy; |
| 4295 const gchar *name, *alias; |
4294 const gchar *name, *alias; |
| 4296 gchar *tmp, *alias_key; |
4295 gchar *tmp, *alias_key; |
| 4297 PurpleChatUserFlags flags; |
4296 PurpleChatUserFlags flags; |
| 4298 GdkColor *color = NULL; |
4297 GdkRGBA *color = NULL; |
| 4299 |
4298 |
| 4300 alias = purple_chat_user_get_alias(cb); |
4299 alias = purple_chat_user_get_alias(cb); |
| 4301 name = purple_chat_user_get_name(cb); |
4300 name = purple_chat_user_get_name(cb); |
| 4302 flags = purple_chat_user_get_flags(cb); |
4301 flags = purple_chat_user_get_flags(cb); |
| 4303 |
4302 |
| 4327 #if 0 |
4326 #if 0 |
| 4328 /* TODO WEBKIT: No tags in webkit stuff, yet. */ |
4327 /* TODO WEBKIT: No tags in webkit stuff, yet. */ |
| 4329 GtkTextTag *tag = gtk_text_tag_table_lookup( |
4328 GtkTextTag *tag = gtk_text_tag_table_lookup( |
| 4330 gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->webview)->text_buffer), |
4329 gtk_text_buffer_get_tag_table(GTK_IMHTML(gtkconv->webview)->text_buffer), |
| 4331 "send-name"); |
4330 "send-name"); |
| 4332 g_object_get(tag, "foreground-gdk", &color, NULL); |
4331 g_object_get(tag, "foreground-rgba", &color, NULL); |
| 4333 #endif /* if 0 */ |
4332 #endif /* if 0 */ |
| 4334 } else { |
4333 } else { |
| 4335 GtkTextTag *tag; |
4334 GtkTextTag *tag; |
| 4336 if ((tag = get_buddy_tag(chat, name, 0, FALSE))) |
4335 if ((tag = get_buddy_tag(chat, name, 0, FALSE))) |
| 4337 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL); |
4336 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL); |
| 4338 if ((tag = get_buddy_tag(chat, name, PURPLE_MESSAGE_NICK, FALSE))) |
4337 if ((tag = get_buddy_tag(chat, name, PURPLE_MESSAGE_NICK, FALSE))) |
| 4339 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL); |
4338 g_object_set(G_OBJECT(tag), "style", PANGO_STYLE_NORMAL, NULL); |
| 4340 color = (GdkColor*)get_nick_color(gtkconv, name); |
4339 color = (GdkRGBA*)get_nick_color(gtkconv, name); |
| 4341 } |
4340 } |
| 4342 |
4341 |
| 4343 gtk_list_store_insert_with_values(ls, &iter, |
4342 gtk_list_store_insert_with_values(ls, &iter, |
| 4344 /* |
4343 /* |
| 4345 * The GTK docs are mute about the effects of the "row" value for performance. |
4344 * The GTK docs are mute about the effects of the "row" value for performance. |
| 5104 |
5103 |
| 5105 /* Setup the list of users. */ |
5104 /* Setup the list of users. */ |
| 5106 |
5105 |
| 5107 ls = gtk_list_store_new(CHAT_USERS_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, |
5106 ls = gtk_list_store_new(CHAT_USERS_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING, |
| 5108 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, |
5107 G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, |
| 5109 GDK_TYPE_COLOR, G_TYPE_INT, G_TYPE_STRING); |
5108 GDK_TYPE_RGBA, G_TYPE_INT, G_TYPE_STRING); |
| 5110 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(ls), CHAT_USERS_ALIAS_KEY_COLUMN, |
5109 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(ls), CHAT_USERS_ALIAS_KEY_COLUMN, |
| 5111 sort_chat_users, NULL, NULL); |
5110 sort_chat_users, NULL, NULL); |
| 5112 |
5111 |
| 5113 list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ls)); |
5112 list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ls)); |
| 5114 |
5113 |
| 5149 NULL); |
5148 NULL); |
| 5150 g_object_set(G_OBJECT(rend), "editable", TRUE, NULL); |
5149 g_object_set(G_OBJECT(rend), "editable", TRUE, NULL); |
| 5151 |
5150 |
| 5152 col = gtk_tree_view_column_new_with_attributes(NULL, rend, |
5151 col = gtk_tree_view_column_new_with_attributes(NULL, rend, |
| 5153 "text", CHAT_USERS_ALIAS_COLUMN, |
5152 "text", CHAT_USERS_ALIAS_COLUMN, |
| 5154 "foreground-gdk", CHAT_USERS_COLOR_COLUMN, |
5153 "foreground-rgba", CHAT_USERS_COLOR_COLUMN, |
| 5155 "weight", CHAT_USERS_WEIGHT_COLUMN, |
5154 "weight", CHAT_USERS_WEIGHT_COLUMN, |
| 5156 NULL); |
5155 NULL); |
| 5157 |
5156 |
| 5158 purple_signal_connect(blist_handle, "blist-node-added", |
5157 purple_signal_connect(blist_handle, "blist-node-added", |
| 5159 gtkchat, PURPLE_CALLBACK(buddy_added_cb), conv); |
5158 gtkchat, PURPLE_CALLBACK(buddy_added_cb), conv); |
| 5890 static void set_typing_font(GtkWidget *widget, GtkStyle *style, PidginConversation *gtkconv) |
5889 static void set_typing_font(GtkWidget *widget, GtkStyle *style, PidginConversation *gtkconv) |
| 5891 { |
5890 { |
| 5892 /* TODO WEBKIT */ |
5891 /* TODO WEBKIT */ |
| 5893 #if 0 |
5892 #if 0 |
| 5894 static PangoFontDescription *font_desc = NULL; |
5893 static PangoFontDescription *font_desc = NULL; |
| 5895 static GdkColor *color = NULL; |
5894 static GdkRGBA *color = NULL; |
| 5896 static gboolean enable = TRUE; |
5895 static gboolean enable = TRUE; |
| 5897 |
5896 |
| 5898 if (font_desc == NULL) { |
5897 if (font_desc == NULL) { |
| 5899 char *string = NULL; |
5898 char *string = NULL; |
| 5900 gtk_widget_style_get(widget, |
5899 gtk_widget_style_get(widget, |
| 5903 "typing-notification-enable", &enable, |
5902 "typing-notification-enable", &enable, |
| 5904 NULL); |
5903 NULL); |
| 5905 font_desc = pango_font_description_from_string(string); |
5904 font_desc = pango_font_description_from_string(string); |
| 5906 g_free(string); |
5905 g_free(string); |
| 5907 if (color == NULL) { |
5906 if (color == NULL) { |
| 5908 GdkColor def = {0, 0x8888, 0x8888, 0x8888}; |
5907 GdkRGBA def = {0x8888/65535.0f, 0x8888/65535.0f, 0x8888/65535.0f, 1.0}; |
| 5909 color = gdk_color_copy(&def); |
5908 color = gdk_rgba_copy(&def); |
| 5910 } |
5909 } |
| 5911 } |
5910 } |
| 5912 |
5911 |
| 5913 gtk_text_buffer_create_tag(GTK_IMHTML(widget)->text_buffer, "TYPING-NOTIFICATION", |
5912 gtk_text_buffer_create_tag(GTK_IMHTML(widget)->text_buffer, "TYPING-NOTIFICATION", |
| 5914 "foreground-gdk", color, |
5913 "foreground-rgba", color, |
| 5915 "font-desc", font_desc, |
5914 "font-desc", font_desc, |
| 5916 NULL); |
5915 NULL); |
| 5917 |
5916 |
| 5918 if (!enable) { |
5917 if (!enable) { |
| 5919 g_object_set_data(G_OBJECT(widget), "disable-typing-notification", GINT_TO_POINTER(TRUE)); |
5918 g_object_set_data(G_OBJECT(widget), "disable-typing-notification", GINT_TO_POINTER(TRUE)); |
| 6063 pidgin_conv_window_add_gtkconv(hidden_convwin, gtkconv); |
6062 pidgin_conv_window_add_gtkconv(hidden_convwin, gtkconv); |
| 6064 else |
6063 else |
| 6065 pidgin_conv_placement_place(gtkconv); |
6064 pidgin_conv_placement_place(gtkconv); |
| 6066 |
6065 |
| 6067 if (generated_nick_colors == NULL) { |
6066 if (generated_nick_colors == NULL) { |
| 6068 generated_nick_colors = generate_nick_colors(NICK_COLOR_GENERATE_COUNT, gtk_widget_get_style(gtkconv->webview)->base[GTK_STATE_NORMAL]); |
6067 GdkColor color; |
| |
6068 GdkRGBA rgba; |
| |
6069 /* FIXME: No matter how I ask the GtkStyleContext, it always gives me |
| |
6070 * back black instead of the _actual_ background colour. */ |
| |
6071 color = gtk_widget_get_style(gtkconv->webview)->base[GTK_STATE_NORMAL]; |
| |
6072 rgba.red = color.red / 65535.0f; |
| |
6073 rgba.green = color.green / 65535.0f; |
| |
6074 rgba.blue = color.blue / 65535.0f; |
| |
6075 generated_nick_colors = generate_nick_colors(NICK_COLOR_GENERATE_COUNT, rgba); |
| 6069 } |
6076 } |
| 6070 |
6077 |
| 6071 if(NULL == (gtkconv->nick_colors = pidgin_conversation_theme_get_nick_colors(gtkconv->theme))) |
6078 if(NULL == (gtkconv->nick_colors = pidgin_conversation_theme_get_nick_colors(gtkconv->theme))) |
| 6072 { |
6079 { |
| 6073 gtkconv->nick_colors = g_array_ref(generated_nick_colors); |
6080 gtkconv->nick_colors = g_array_ref(generated_nick_colors); |
| 6190 |
6197 |
| 6191 #if 0 |
6198 #if 0 |
| 6192 static const char * |
6199 static const char * |
| 6193 get_text_tag_color(GtkTextTag *tag) |
6200 get_text_tag_color(GtkTextTag *tag) |
| 6194 { |
6201 { |
| 6195 GdkColor *color = NULL; |
6202 GdkRGBA *color = NULL; |
| 6196 gboolean set = FALSE; |
6203 gboolean set = FALSE; |
| 6197 static char colcode[] = "#XXXXXX"; |
6204 static char colcode[] = "#XXXXXX"; |
| 6198 if (tag) |
6205 if (tag) |
| 6199 g_object_get(G_OBJECT(tag), "foreground-set", &set, "foreground-gdk", &color, NULL); |
6206 g_object_get(G_OBJECT(tag), "foreground-set", &set, "foreground-rgba", &color, NULL); |
| 6200 if (set && color) |
6207 if (set && color) |
| 6201 g_snprintf(colcode, sizeof(colcode), "#%02x%02x%02x", |
6208 g_snprintf(colcode, sizeof(colcode), "#%02x%02x%02x", |
| 6202 color->red >> 8, color->green >> 8, color->blue >> 8); |
6209 (unsigned int)(color->red * 255), |
| |
6210 (unsigned int)(color->green * 255), |
| |
6211 (unsigned int)(color->blue * 255)); |
| 6203 else |
6212 else |
| 6204 colcode[0] = '\0'; |
6213 colcode[0] = '\0'; |
| 6205 if (color) |
6214 if (color) |
| 6206 gdk_color_free(color); |
6215 gdk_rgba_free(color); |
| 6207 return colcode; |
6216 return colcode; |
| 6208 } |
6217 } |
| 6209 |
6218 |
| 6210 /* The callback for an event on a link tag. */ |
6219 /* The callback for an event on a link tag. */ |
| 6211 static gboolean buddytag_event(GtkTextTag *tag, GObject *imhtml, |
6220 static gboolean buddytag_event(GtkTextTag *tag, GObject *imhtml, |
| 6303 "weight", PANGO_WEIGHT_BOLD, |
6312 "weight", PANGO_WEIGHT_BOLD, |
| 6304 NULL); |
6313 NULL); |
| 6305 else |
6314 else |
| 6306 buddytag = gtk_text_buffer_create_tag( |
6315 buddytag = gtk_text_buffer_create_tag( |
| 6307 buffer, str, |
6316 buffer, str, |
| 6308 "foreground-gdk", get_nick_color(gtkconv, who), |
6317 "foreground-rgba", get_nick_color(gtkconv, who), |
| 6309 "weight", purple_blist_find_buddy(purple_conversation_get_account(conv), who) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, |
6318 "weight", purple_blist_find_buddy(purple_conversation_get_account(conv), who) ? PANGO_WEIGHT_BOLD : PANGO_WEIGHT_NORMAL, |
| 6310 NULL); |
6319 NULL); |
| 6311 |
6320 |
| 6312 g_object_set_data(G_OBJECT(buddytag), "cursor", ""); |
6321 g_object_set_data(G_OBJECT(buddytag), "cursor", ""); |
| 6313 g_signal_connect(G_OBJECT(buddytag), "event", |
6322 g_signal_connect(G_OBJECT(buddytag), "event", |
| 6467 |
6476 |
| 6468 } else if (g_str_has_prefix(cur, "%sender%")) { |
6477 } else if (g_str_has_prefix(cur, "%sender%")) { |
| 6469 replace = alias; |
6478 replace = alias; |
| 6470 |
6479 |
| 6471 } else if (g_str_has_prefix(cur, "%senderColor%")) { |
6480 } else if (g_str_has_prefix(cur, "%senderColor%")) { |
| 6472 const GdkColor *color = get_nick_color(PIDGIN_CONVERSATION(conv), name); |
6481 const GdkRGBA *color = get_nick_color(PIDGIN_CONVERSATION(conv), name); |
| 6473 replace = freeval = g_strdup_printf("#%02x%02x%02x", (color->red >> 8), (color->green >> 8), (color->blue >> 8)); |
6482 replace = freeval = g_strdup_printf("#%02x%02x%02x", |
| |
6483 (unsigned int)(color->red * 255), |
| |
6484 (unsigned int)(color->green * 255), |
| |
6485 (unsigned int)(color->blue * 255)); |
| 6474 |
6486 |
| 6475 } else if (g_str_has_prefix(cur, "%service%")) { |
6487 } else if (g_str_has_prefix(cur, "%service%")) { |
| 6476 replace = purple_account_get_protocol_name(purple_conversation_get_account(conv)); |
6488 replace = purple_account_get_protocol_name(purple_conversation_get_account(conv)); |
| 6477 |
6489 |
| 6478 } else if (g_str_has_prefix(cur, "%messageDirection%")) { |
6490 } else if (g_str_has_prefix(cur, "%messageDirection%")) { |
| 11138 |
11150 |
| 11139 return (gtkconv->win == hidden_convwin); |
11151 return (gtkconv->win == hidden_convwin); |
| 11140 } |
11152 } |
| 11141 |
11153 |
| 11142 |
11154 |
| 11143 gfloat luminance(GdkColor color) |
11155 gfloat luminance(GdkRGBA color) |
| 11144 { |
11156 { |
| 11145 gfloat r, g, b; |
11157 gfloat r, g, b; |
| 11146 gfloat rr, gg, bb; |
11158 gfloat rr, gg, bb; |
| 11147 gfloat cutoff = 0.03928, scale = 12.92; |
11159 gfloat cutoff = 0.03928, scale = 12.92; |
| 11148 gfloat a = 0.055, d = 1.055, p = 2.2; |
11160 gfloat a = 0.055, d = 1.055, p = 2.2; |
| 11149 gfloat sRGBScale = 65535.0; |
11161 |
| 11150 |
11162 rr = color.red; |
| 11151 /* Normalizing color values to [0,1] from the sRGB space.*/ |
11163 gg = color.green; |
| 11152 rr = (float)(color.red)/sRGBScale; |
11164 bb = color.blue; |
| 11153 gg = (float)(color.green)/sRGBScale; |
|
| 11154 bb = (float)(color.blue)/sRGBScale; |
|
| 11155 |
11165 |
| 11156 r = (rr > cutoff) ? pow((rr+a)/d, p) : rr/scale; |
11166 r = (rr > cutoff) ? pow((rr+a)/d, p) : rr/scale; |
| 11157 g = (gg > cutoff) ? pow((gg+a)/d, p) : gg/scale; |
11167 g = (gg > cutoff) ? pow((gg+a)/d, p) : gg/scale; |
| 11158 b = (bb > cutoff) ? pow((bb+a)/d, p) : bb/scale; |
11168 b = (bb > cutoff) ? pow((bb+a)/d, p) : bb/scale; |
| 11159 |
11169 |
| 11160 return (r*0.2126 + g*0.7152 + b*0.0722); |
11170 return (r*0.2126 + g*0.7152 + b*0.0722); |
| 11161 } |
11171 } |
| 11162 |
11172 |
| 11163 /* Algorithm from https://www.w3.org/TR/2008/REC-WCAG20-20081211/relative-luminance.xml */ |
11173 /* Algorithm from https://www.w3.org/TR/2008/REC-WCAG20-20081211/relative-luminance.xml */ |
| 11164 static gboolean |
11174 static gboolean |
| 11165 color_is_visible(GdkColor foreground, GdkColor background, gfloat min_contrast_ratio) |
11175 color_is_visible(GdkRGBA foreground, GdkRGBA background, gfloat min_contrast_ratio) |
| 11166 { |
11176 { |
| 11167 gfloat lfg, lbg, lmin, lmax; |
11177 gfloat lfg, lbg, lmin, lmax; |
| 11168 gfloat luminosity_ratio; |
11178 gfloat luminosity_ratio; |
| |
11179 gfloat nr, dr; |
| 11169 |
11180 |
| 11170 lfg = luminance(foreground); |
11181 lfg = luminance(foreground); |
| 11171 lbg = luminance(background); |
11182 lbg = luminance(background); |
| 11172 |
11183 |
| 11173 if (lfg > lbg) |
11184 if (lfg > lbg) |
| 11174 lmax = lfg, lmin = lbg; |
11185 lmax = lfg, lmin = lbg; |
| 11175 else |
11186 else |
| 11176 lmax = lbg, lmin = lfg; |
11187 lmax = lbg, lmin = lfg; |
| 11177 |
11188 |
| 11178 gfloat nr, dr; |
|
| 11179 nr = lmax + 0.05, dr = lmin - 0.05; |
11189 nr = lmax + 0.05, dr = lmin - 0.05; |
| 11180 if ( dr == 0 ) |
11190 if ( dr == 0 ) |
| 11181 dr += 0.01; |
11191 dr += 0.01; |
| 11182 |
11192 |
| 11183 luminosity_ratio = nr/dr; |
11193 luminosity_ratio = nr/dr; |
| 11186 return (luminosity_ratio > min_contrast_ratio); |
11196 return (luminosity_ratio > min_contrast_ratio); |
| 11187 } |
11197 } |
| 11188 |
11198 |
| 11189 |
11199 |
| 11190 static GArray* |
11200 static GArray* |
| 11191 generate_nick_colors(guint numcolors, GdkColor background) |
11201 generate_nick_colors(guint numcolors, GdkRGBA background) |
| 11192 { |
11202 { |
| 11193 guint i = 0, j = 0; |
11203 guint i = 0, j = 0; |
| 11194 GArray *colors = g_array_new(FALSE, FALSE, sizeof(GdkColor)); |
11204 GArray *colors = g_array_new(FALSE, FALSE, sizeof(GdkRGBA)); |
| 11195 GdkColor nick_highlight; |
11205 GdkRGBA nick_highlight; |
| 11196 GdkColor send_color; |
11206 GdkRGBA send_color; |
| 11197 time_t breakout_time; |
11207 time_t breakout_time; |
| 11198 |
11208 |
| 11199 gdk_color_parse(DEFAULT_HIGHLIGHT_COLOR, &nick_highlight); |
11209 gdk_rgba_parse(&nick_highlight, DEFAULT_HIGHLIGHT_COLOR); |
| 11200 gdk_color_parse(DEFAULT_SEND_COLOR, &send_color); |
11210 gdk_rgba_parse(&send_color, DEFAULT_SEND_COLOR); |
| 11201 |
11211 |
| 11202 srand(background.red + background.green + background.blue + 1); |
11212 srand(background.red * 65535 + background.green * 65535 + background.blue * 65535 + 1); |
| 11203 |
11213 |
| 11204 breakout_time = time(NULL) + 3; |
11214 breakout_time = time(NULL) + 3; |
| 11205 |
11215 |
| 11206 /* first we look through the list of "good" colors: colors that differ from every other color in the |
11216 /* first we look through the list of "good" colors: colors that differ from every other color in the |
| 11207 * list. only some of them will differ from the background color though. lets see if we can find |
11217 * list. only some of them will differ from the background color though. lets see if we can find |
| 11208 * numcolors of them that do |
11218 * numcolors of them that do |
| 11209 */ |
11219 */ |
| 11210 while (i < numcolors && j < PIDGIN_NUM_NICK_SEED_COLORS && time(NULL) < breakout_time) |
11220 while (i < numcolors && j < PIDGIN_NUM_NICK_SEED_COLORS && time(NULL) < breakout_time) |
| 11211 { |
11221 { |
| 11212 GdkColor color = nick_seed_colors[j]; |
11222 GdkRGBA color = nick_seed_colors[j]; |
| 11213 |
11223 |
| 11214 if (color_is_visible(color, background, MIN_LUMINANCE_CONTRAST_RATIO) && |
11224 if (color_is_visible(color, background, MIN_LUMINANCE_CONTRAST_RATIO) && |
| 11215 color_is_visible(color, nick_highlight, MIN_LUMINANCE_CONTRAST_RATIO) && |
11225 color_is_visible(color, nick_highlight, MIN_LUMINANCE_CONTRAST_RATIO) && |
| 11216 color_is_visible(color, send_color, MIN_LUMINANCE_CONTRAST_RATIO)) |
11226 color_is_visible(color, send_color, MIN_LUMINANCE_CONTRAST_RATIO)) |
| 11217 { |
11227 { |
| 11226 * expensive to find colors that not only don't conflict with the background, but also do not |
11236 * expensive to find colors that not only don't conflict with the background, but also do not |
| 11227 * conflict with each other. |
11237 * conflict with each other. |
| 11228 */ |
11238 */ |
| 11229 while(i < numcolors && time(NULL) < breakout_time) |
11239 while(i < numcolors && time(NULL) < breakout_time) |
| 11230 { |
11240 { |
| 11231 GdkColor color = { 0, rand() % 65536, rand() % 65536, rand() % 65536 }; |
11241 GdkRGBA color = {rand() % 65536 / 65535.f, rand() % 65536 / 65535.f, rand() % 65536 / 65535.f, 1}; |
| 11232 |
11242 |
| 11233 if (color_is_visible(color, background, MIN_LUMINANCE_CONTRAST_RATIO) && |
11243 if (color_is_visible(color, background, MIN_LUMINANCE_CONTRAST_RATIO) && |
| 11234 color_is_visible(color, nick_highlight, MIN_LUMINANCE_CONTRAST_RATIO) && |
11244 color_is_visible(color, nick_highlight, MIN_LUMINANCE_CONTRAST_RATIO) && |
| 11235 color_is_visible(color, send_color, MIN_LUMINANCE_CONTRAST_RATIO)) |
11245 color_is_visible(color, send_color, MIN_LUMINANCE_CONTRAST_RATIO)) |
| 11236 { |
11246 { |
| 11243 purple_debug_warning("gtkconv", "Unable to generate enough random colors before timeout. %u colors found.\n", i); |
11253 purple_debug_warning("gtkconv", "Unable to generate enough random colors before timeout. %u colors found.\n", i); |
| 11244 } |
11254 } |
| 11245 |
11255 |
| 11246 if( i == 0 ) { |
11256 if( i == 0 ) { |
| 11247 /* To remove errors caused by an empty array. */ |
11257 /* To remove errors caused by an empty array. */ |
| 11248 GdkColor color = {0, 32768, 32768, 32768}; |
11258 GdkRGBA color = {0.5, 0.5, 0.5, 1.0}; |
| 11249 g_array_append_val(colors, color); |
11259 g_array_append_val(colors, color); |
| 11250 } |
11260 } |
| 11251 |
11261 |
| 11252 return colors; |
11262 return colors; |
| 11253 } |
11263 } |