107 gchar *thumb_path = g_build_filename(path,
"thumbnailers", NULL);
109 GDir *dir = g_dir_open(thumb_path, 0, NULL);
118 while ((dirent = g_dir_read_name(dir))) {
122 gchar *filename = g_build_filename(thumb_path, dirent, NULL);
123 GKeyFile *key_file = g_key_file_new();
124 GError *error = NULL;
126 if (!g_key_file_load_from_file(key_file, filename, 0, &error)) {
127 g_warning(
"Error loading thumbnailer %s: %s", filename, error->message);
132 gchar **mime_types = g_key_file_get_string_list(
135 if (mime_types && command) {
137 for (i = 0; mime_types[i] != NULL; i++) {
140 g_info(
"Loading thumbnailer %s for mimetype %s", filename,
143 g_strdup(mime_types[i]), g_strdup(command));
149 g_strfreev(mime_types);
154 g_key_file_free(key_file);
163 const gchar *filename,
164 const gchar *encoded_uri,
165 const gchar *output_path,
int size) {
166 gchar **command_parts = g_strsplit(command,
" ", 0);
167 guint command_parts_count = g_strv_length(command_parts);
169 gchar **command_args = NULL;
172 command_args = g_malloc0(
sizeof(gchar *) * (command_parts_count + 3 + 1));
175 guint current_index = 0;
177 command_args[current_index++] = g_strdup(
"nice");
178 command_args[current_index++] = g_strdup(
"-n");
179 command_args[current_index++] = g_strdup(
"19");
183 for (i = 0; command_parts[i] != NULL; i++) {
184 if (strcmp(command_parts[i],
"%i") == 0) {
185 command_args[current_index++] = g_strdup(filename);
186 }
else if (strcmp(command_parts[i],
"%u") == 0) {
187 command_args[current_index++] = g_strdup(encoded_uri);
188 }
else if (strcmp(command_parts[i],
"%o") == 0) {
189 command_args[current_index++] = g_strdup(output_path);
190 }
else if (strcmp(command_parts[i],
"%s") == 0) {
191 command_args[current_index++] = g_strdup_printf(
"%d", size);
193 command_args[current_index++] = g_strdup(command_parts[i]);
197 command_args[current_index++] = NULL;
199 g_strfreev(command_parts);
288 g_hash_table_new(g_direct_hash, g_direct_equal);
292 GSList *l = gdk_pixbuf_get_formats();
293 for (GSList *li = l; li != NULL; li = g_slist_next(li)) {
295 gdk_pixbuf_format_get_extensions((GdkPixbufFormat *)li->data);
297 for (
unsigned int i = 0; exts && exts[i]; i++) {
300 g_info(
"Add image extension: %s", exts[i]);
310 g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_free);
312 const gchar *
const *system_data_dirs = g_get_system_data_dirs();
313 const gchar *user_data_dir = g_get_user_data_dir();
318 for (i = 0; system_data_dirs[i] != NULL; i++) {
390 const guchar *pixels;
394 if (pixbuf == NULL) {
398 width = gdk_pixbuf_get_width(pixbuf);
399 height = gdk_pixbuf_get_height(pixbuf);
400 pixels = gdk_pixbuf_read_pixels(pixbuf);
401 stride = gdk_pixbuf_get_rowstride(pixbuf);
402 alpha = gdk_pixbuf_get_has_alpha(pixbuf);
404 cairo_surface_t *surface = NULL;
409 const guchar *pixels_end, *line;
412 pixels_end = pixels + height * stride;
416 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
417 cpixels = cairo_image_surface_get_data(surface);
418 cstride = cairo_image_surface_get_stride(surface);
420 cairo_surface_flush(surface);
421 while (pixels < pixels_end) {
423 const guchar *line_end = line + lo;
424 guchar *cline = cpixels;
426 while (line < line_end) {
442 cairo_surface_mark_dirty(surface);
443 cairo_surface_flush(surface);
471 GChecksum *checksum = g_checksum_new(G_CHECKSUM_MD5);
472 g_checksum_update(checksum, (guchar *)name, -1);
473 const gchar *md5_hex = g_checksum_get_string(checksum);
476 const gchar *
cache_dir = g_get_user_cache_dir();
480 if (requested_size <= 128) {
482 thumb_dir = g_strconcat(
cache_dir,
"/thumbnails/normal/", NULL);
484 g_strconcat(
cache_dir,
"/thumbnails/normal/", md5_hex,
".png", NULL);
485 }
else if (requested_size <= 256) {
487 thumb_dir = g_strconcat(
cache_dir,
"/thumbnails/large/", NULL);
489 g_strconcat(
cache_dir,
"/thumbnails/large/", md5_hex,
".png", NULL);
490 }
else if (requested_size <= 512) {
492 thumb_dir = g_strconcat(
cache_dir,
"/thumbnails/x-large/", NULL);
494 g_strconcat(
cache_dir,
"/thumbnails/x-large/", md5_hex,
".png", NULL);
497 thumb_dir = g_strconcat(
cache_dir,
"/thumbnails/xx-large/", NULL);
499 g_strconcat(
cache_dir,
"/thumbnails/xx-large/", md5_hex,
".png", NULL);
503 g_mkdir_with_parents(thumb_dir, 0700);
506 g_checksum_free(checksum);
534 G_GNUC_UNUSED gpointer user_data) {
535 g_debug(
"starting up icon fetching thread.");
541 const gchar *icon_path;
542 gchar *icon_path_ = NULL;
544 if (g_str_has_prefix(sentry->
entry->
name,
"thumbnail://")) {
546 gchar *entry_name = &sentry->
entry->
name[12];
548 if (strcmp(entry_name,
"") == 0) {
556 int requested_size = MAX(sentry->
wsize, sentry->
hsize);
560 entry_name, requested_size, &thumb_size);
562 if (!g_file_test(icon_path, G_FILE_TEST_EXISTS)) {
563 char **command_args = NULL;
565 gchar *size_str = g_strdup_printf(
"%d", thumb_size);
568 entry_name,
"{output}", icon_path_,
"{size}",
575 g_strfreev(command_args);
578 }
else if (g_path_is_absolute(entry_name)) {
580 if (g_str_has_suffix(entry_name,
".desktop")) {
584 if (icon_key == NULL || strlen(icon_key) == 0) {
586 icon_path = icon_path_ = nk_xdg_theme_get_icon(
591 }
else if (g_path_is_absolute(icon_key)) {
593 icon_path = icon_path_ = icon_key;
596 icon_path = icon_path_ = nk_xdg_theme_get_icon(
604 gchar *encoded_uri = g_filename_to_uri(entry_name, NULL, NULL);
605 int requested_size = MAX(sentry->
wsize, sentry->
hsize);
610 encoded_uri, requested_size, &thumb_size);
612 if (!g_file_test(icon_path, G_FILE_TEST_EXISTS)) {
614 char *content_type = g_content_type_guess(entry_name, NULL, 0, NULL);
615 char *mime_type = g_content_type_get_mime_type(content_type);
619 mime_type, entry_name, encoded_uri, icon_path_, thumb_size);
625 while (mime_type[index]) {
626 if (mime_type[index] ==
'/')
627 mime_type[index] =
'-';
634 icon_path = icon_path_ = nk_xdg_theme_get_icon(
640 g_free(content_type);
649 if (icon_path_ == NULL || !g_file_test(icon_path, G_FILE_TEST_EXISTS)) {
654 }
else if (g_path_is_absolute(sentry->
entry->
name)) {
656 }
else if (g_str_has_prefix(sentry->
entry->
name,
"<span")) {
657 cairo_surface_t *surface = cairo_image_surface_create(
658 CAIRO_FORMAT_ARGB32, sentry->
wsize, sentry->
hsize);
659 cairo_t *cr = cairo_create(surface);
660 PangoLayout *layout = pango_cairo_create_layout(cr);
661 pango_layout_set_markup(layout, sentry->
entry->
name, -1);
664 pango_layout_get_size(layout, &width, &height);
665 double ws = sentry->
wsize / ((double)width / PANGO_SCALE);
666 double wh = sentry->
hsize / ((double)height / PANGO_SCALE);
667 double scale = MIN(ws, wh);
670 cr, (sentry->
wsize - ((
double)width / PANGO_SCALE) * scale) / 2.0,
671 (sentry->
hsize - ((
double)height / PANGO_SCALE) * scale) / 2.0);
672 cairo_scale(cr, scale, scale);
673 pango_cairo_update_layout(cr, layout);
674 pango_layout_get_size(layout, &width, &height);
675 pango_cairo_show_layout(cr, layout);
676 g_object_unref(layout);
684 icon_path = icon_path_ = nk_xdg_theme_get_icon(
687 if (icon_path_ == NULL) {
688 g_debug(
"failed to get icon %s(%dx%d): n/a", sentry->
entry->
name,
691 const char *ext = g_strrstr(sentry->
entry->
name,
".");
693 const char *exts2[2] = {ext, NULL};
694 icon_path = icon_path_ =
697 if (icon_path_ == NULL) {
703 g_debug(
"found icon %s(%dx%d): %s", sentry->
entry->
name, sentry->
wsize,
704 sentry->
hsize, icon_path);
707 cairo_surface_t *icon_surf = NULL;
710 const char *suf = strrchr(icon_path,
'.');
719 int width = sentry->
wsize, height = sentry->
hsize;
721 width *= sentry->
scale;
723 height *= sentry->
scale;
725 GError *error = NULL;
727 gdk_pixbuf_new_from_file_at_scale(icon_path, width, height, TRUE, &error);
734 if (error != NULL && g_error_matches(error, GDK_PIXBUF_ERROR,
735 GDK_PIXBUF_ERROR_INCOMPLETE_ANIMATION)) {
736 g_clear_error(&error);
740 g_warning(
"Failed to load image: |%s| %d %d %s (%p)", icon_path,
741 sentry->
wsize, sentry->
hsize, error->message, (
void *)pb);
IconFetcherNameEntry * entry