106 gchar *thumb_path = g_build_filename(path,
"thumbnailers", NULL);
108 GDir *dir = g_dir_open(thumb_path, 0, NULL);
117 while ((dirent = g_dir_read_name(dir))) {
121 gchar *filename = g_build_filename(thumb_path, dirent, NULL);
122 GKeyFile *key_file = g_key_file_new();
123 GError *error = NULL;
125 if (!g_key_file_load_from_file(key_file, filename, 0, &error)) {
126 g_warning(
"Error loading thumbnailer %s: %s", filename, error->message);
131 gchar **mime_types = g_key_file_get_string_list(
134 if (mime_types && command) {
136 for (i = 0; mime_types[i] != NULL; i++) {
139 g_info(
"Loading thumbnailer %s for mimetype %s", filename,
142 g_strdup(mime_types[i]), g_strdup(command));
148 g_strfreev(mime_types);
153 g_key_file_free(key_file);
162 const gchar *filename,
163 const gchar *encoded_uri,
164 const gchar *output_path,
int size) {
165 gchar **command_parts = g_strsplit(command,
" ", 0);
166 guint command_parts_count = g_strv_length(command_parts);
168 gchar **command_args = NULL;
171 command_args = g_malloc0(
sizeof(gchar *) * (command_parts_count + 3 + 1));
174 guint current_index = 0;
176 command_args[current_index++] = g_strdup(
"nice");
177 command_args[current_index++] = g_strdup(
"-n");
178 command_args[current_index++] = g_strdup(
"19");
182 for (i = 0; command_parts[i] != NULL; i++) {
183 if (strcmp(command_parts[i],
"%i") == 0) {
184 command_args[current_index++] = g_strdup(filename);
185 }
else if (strcmp(command_parts[i],
"%u") == 0) {
186 command_args[current_index++] = g_strdup(encoded_uri);
187 }
else if (strcmp(command_parts[i],
"%o") == 0) {
188 command_args[current_index++] = g_strdup(output_path);
189 }
else if (strcmp(command_parts[i],
"%s") == 0) {
190 command_args[current_index++] = g_strdup_printf(
"%d", size);
192 command_args[current_index++] = g_strdup(command_parts[i]);
196 command_args[current_index++] = NULL;
198 g_strfreev(command_parts);
276 static const gchar *
const icon_fallback_themes[] = {
"Adwaita",
"gnome", NULL};
277 const char *themes[2] = {
config.icon_theme, NULL};
282 nk_xdg_theme_context_new(icon_fallback_themes, NULL);
286 g_hash_table_new(g_direct_hash, g_direct_equal);
290 GSList *l = gdk_pixbuf_get_formats();
291 for (GSList *li = l; li != NULL; li = g_slist_next(li)) {
293 gdk_pixbuf_format_get_extensions((GdkPixbufFormat *)li->data);
295 for (
unsigned int i = 0; exts && exts[i]; i++) {
298 g_info(
"Add image extension: %s", exts[i]);
308 g_str_hash, g_str_equal, (GDestroyNotify)g_free, (GDestroyNotify)g_free);
310 const gchar *
const *system_data_dirs = g_get_system_data_dirs();
311 const gchar *user_data_dir = g_get_user_data_dir();
316 for (i = 0; system_data_dirs[i] != NULL; i++) {
385 const guchar *pixels;
389 if (pixbuf == NULL) {
393 width = gdk_pixbuf_get_width(pixbuf);
394 height = gdk_pixbuf_get_height(pixbuf);
395 pixels = gdk_pixbuf_read_pixels(pixbuf);
396 stride = gdk_pixbuf_get_rowstride(pixbuf);
397 alpha = gdk_pixbuf_get_has_alpha(pixbuf);
399 cairo_surface_t *surface = NULL;
404 const guchar *pixels_end, *line;
407 pixels_end = pixels + height * stride;
411 surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
412 cpixels = cairo_image_surface_get_data(surface);
413 cstride = cairo_image_surface_get_stride(surface);
415 cairo_surface_flush(surface);
416 while (pixels < pixels_end) {
418 const guchar *line_end = line + lo;
419 guchar *cline = cpixels;
421 while (line < line_end) {
437 cairo_surface_mark_dirty(surface);
438 cairo_surface_flush(surface);
529 G_GNUC_UNUSED gpointer user_data) {
530 g_debug(
"starting up icon fetching thread.");
534 const gchar *themes[] = {
config.icon_theme, NULL};
536 const gchar *icon_path;
537 gchar *icon_path_ = NULL;
539 if (g_str_has_prefix(sentry->
entry->
name,
"thumbnail://")) {
541 gchar *entry_name = &sentry->
entry->
name[12];
543 if (strcmp(entry_name,
"") == 0) {
550 if (
config.preview_cmd != NULL) {
551 int requested_size = MAX(sentry->
wsize, sentry->
hsize);
555 entry_name, requested_size, &thumb_size);
557 if (!g_file_test(icon_path, G_FILE_TEST_EXISTS)) {
558 char **command_args = NULL;
560 gchar *size_str = g_strdup_printf(
"%d", thumb_size);
563 entry_name,
"{output}", icon_path_,
"{size}",
570 g_strfreev(command_args);
573 }
else if (g_path_is_absolute(entry_name)) {
575 if (g_str_has_suffix(entry_name,
".desktop")) {
579 if (icon_key == NULL || strlen(icon_key) == 0) {
581 icon_path = icon_path_ = nk_xdg_theme_get_icon(
586 }
else if (g_path_is_absolute(icon_key)) {
588 icon_path = icon_path_ = icon_key;
591 icon_path = icon_path_ = nk_xdg_theme_get_icon(
599 gchar *encoded_uri = g_filename_to_uri(entry_name, NULL, NULL);
600 int requested_size = MAX(sentry->
wsize, sentry->
hsize);
605 encoded_uri, requested_size, &thumb_size);
607 if (!g_file_test(icon_path, G_FILE_TEST_EXISTS)) {
609 char *content_type = g_content_type_guess(entry_name, NULL, 0, NULL);
610 char *mime_type = g_content_type_get_mime_type(content_type);
614 mime_type, entry_name, encoded_uri, icon_path_, thumb_size);
620 while (mime_type[index]) {
621 if (mime_type[index] ==
'/')
622 mime_type[index] =
'-';
629 icon_path = icon_path_ = nk_xdg_theme_get_icon(
635 g_free(content_type);
644 if (icon_path_ == NULL || !g_file_test(icon_path, G_FILE_TEST_EXISTS)) {
649 }
else if (g_path_is_absolute(sentry->
entry->
name)) {
651 }
else if (g_str_has_prefix(sentry->
entry->
name,
"<span")) {
652 cairo_surface_t *surface = cairo_image_surface_create(
653 CAIRO_FORMAT_ARGB32, sentry->
wsize, sentry->
hsize);
654 cairo_t *cr = cairo_create(surface);
655 PangoLayout *layout = pango_cairo_create_layout(cr);
656 pango_layout_set_markup(layout, sentry->
entry->
name, -1);
659 pango_layout_get_size(layout, &width, &height);
660 double ws = sentry->
wsize / ((double)width / PANGO_SCALE);
661 double wh = sentry->
hsize / ((double)height / PANGO_SCALE);
662 double scale = MIN(ws, wh);
665 cr, (sentry->
wsize - ((
double)width / PANGO_SCALE) * scale) / 2.0,
666 (sentry->
hsize - ((
double)height / PANGO_SCALE) * scale) / 2.0);
667 cairo_scale(cr, scale, scale);
668 pango_cairo_update_layout(cr, layout);
669 pango_layout_get_size(layout, &width, &height);
670 pango_cairo_show_layout(cr, layout);
671 g_object_unref(layout);
679 icon_path = icon_path_ = nk_xdg_theme_get_icon(
682 if (icon_path_ == NULL) {
683 g_debug(
"failed to get icon %s(%dx%d): n/a", sentry->
entry->
name,
686 const char *ext = g_strrstr(sentry->
entry->
name,
".");
688 const char *exts2[2] = {ext, NULL};
689 icon_path = icon_path_ =
692 if (icon_path_ == NULL) {
698 g_debug(
"found icon %s(%dx%d): %s", sentry->
entry->
name, sentry->
wsize,
699 sentry->
hsize, icon_path);
702 cairo_surface_t *icon_surf = NULL;
705 const char *suf = strrchr(icon_path,
'.');
714 GError *error = NULL;
715 GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_scale(
716 icon_path, sentry->
wsize, sentry->
hsize, TRUE, &error);
723 if (error != NULL && g_error_matches(error, GDK_PIXBUF_ERROR,
724 GDK_PIXBUF_ERROR_INCOMPLETE_ANIMATION)) {
725 g_clear_error(&error);
729 g_warning(
"Failed to load image: |%s| %d %d %s (%p)", icon_path,
730 sentry->
wsize, sentry->
hsize, error->message, (
void *)pb);