"Fossies" - the Fresh Open Source Software Archive

Member "feh-3.4.1/src/index.c" (29 May 2020, 12681 Bytes) of package /linux/privat/feh-3.4.1.tar.bz2:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "index.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 3.4_vs_3.4.1.

    1 /* index.c
    2 
    3 Copyright (C) 1999-2003 Tom Gilbert.
    4 Copyright (C) 2010-2020 Daniel Friesel.
    5 
    6 Permission is hereby granted, free of charge, to any person obtaining a copy
    7 of this software and associated documentation files (the "Software"), to
    8 deal in the Software without restriction, including without limitation the
    9 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   10 sell copies of the Software, and to permit persons to whom the Software is
   11 furnished to do so, subject to the following conditions:
   12 
   13 The above copyright notice and this permission notice shall be included in
   14 all copies of the Software and its documentation and acknowledgment shall be
   15 given in the documentation and software packages that this Software was
   16 used.
   17 
   18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
   21 THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
   22 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
   23 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
   24 
   25 */
   26 
   27 #include "feh.h"
   28 #include "filelist.h"
   29 #include "winwidget.h"
   30 #include "options.h"
   31 #include "index.h"
   32 
   33 
   34 /* TODO Break this up a bit ;) */
   35 /* TODO s/bit/lot */
   36 void init_index_mode(void)
   37 {
   38     Imlib_Load_Error err;
   39     Imlib_Image im_main;
   40     Imlib_Image im_temp;
   41     int w = 800, h = 600, ww = 0, hh = 0, www, hhh, xxx, yyy;
   42     int x = 0, y = 0;
   43     int bg_w = 0, bg_h = 0;
   44     winwidget winwid = NULL;
   45     Imlib_Image bg_im = NULL, im_thumb = NULL;
   46     int tot_thumb_h;
   47     int text_area_h = 50;
   48     int title_area_h = 0;
   49     Imlib_Font fn = NULL;
   50     Imlib_Font title_fn = NULL;
   51     int text_area_w = 0;
   52     int tw = 0, th = 0;
   53     int fw, fh;
   54     int vertical = 0;
   55     int max_column_w = 0;
   56     int thumbnailcount = 0;
   57     gib_list *l = NULL, *last = NULL;
   58     feh_file *file = NULL;
   59     int lineno;
   60     unsigned char trans_bg = 0;
   61     int index_image_width, index_image_height;
   62     gib_list *line, *lines;
   63 
   64     if (opt.montage) {
   65         mode = "montage";
   66     } else {
   67         mode = "index";
   68     }
   69 
   70     if (opt.font)
   71         fn = gib_imlib_load_font(opt.font);
   72 
   73     if (!fn)
   74         fn = gib_imlib_load_font(DEFAULT_FONT);
   75 
   76     if (opt.title_font) {
   77 
   78         title_fn = gib_imlib_load_font(opt.title_font);
   79         if (!title_fn)
   80             title_fn = gib_imlib_load_font(DEFAULT_FONT_TITLE);
   81 
   82         gib_imlib_get_text_size(title_fn, "W", NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT);
   83         title_area_h = fh + 4;
   84     } else
   85         title_fn = gib_imlib_load_font(DEFAULT_FONT_TITLE);
   86 
   87     if ((!fn) || (!title_fn))
   88         eprintf("Error loading fonts");
   89 
   90     /* Work out how tall the font is */
   91     gib_imlib_get_text_size(fn, "W", NULL, &tw, &th, IMLIB_TEXT_TO_RIGHT);
   92     get_index_string_dim(NULL, fn, &fw, &fh);
   93     /* For now, allow room for the right number of lines with small gaps */
   94     text_area_h = fh + 5;
   95 
   96     /* This includes the text area for index data */
   97     tot_thumb_h = opt.thumb_h + text_area_h;
   98 
   99     /* Use bg image dimensions for default size */
  100     if (opt.bg && opt.bg_file) {
  101         if (!strcmp(opt.bg_file, "trans"))
  102             trans_bg = 1;
  103         else {
  104             D(("Time to apply a background to blend onto\n"));
  105             if (feh_load_image_char(&bg_im, opt.bg_file) != 0) {
  106                 bg_w = gib_imlib_image_get_width(bg_im);
  107                 bg_h = gib_imlib_image_get_height(bg_im);
  108             }
  109         }
  110     }
  111 
  112     if (!opt.limit_w && !opt.limit_h) {
  113         if (bg_im) {
  114             opt.limit_w = bg_w;
  115             opt.limit_h = bg_h;
  116         } else
  117             opt.limit_w = 800;
  118     }
  119 
  120     /* Here we need to whiz through the files, and look at the filenames and
  121        info in the selected font, work out how much space we need, and
  122        calculate the size of the image we will require */
  123 
  124     if (opt.limit_w) {
  125         w = opt.limit_w;
  126 
  127         index_calculate_height(fn, w, &h, &tot_thumb_h);
  128 
  129         if (opt.limit_h) {
  130             if (h > opt.limit_h)
  131                 weprintf(
  132                     "The image size you specified (%dx%d) is not large\n"
  133                     "enough to hold all %d thumbnails. To fit all the thumbnails,\n"
  134                     "either decrease their size, choos e asmaller font,\n"
  135                     "or use a larger image (like %dx%d)",
  136                     opt.limit_w, opt.limit_h, filelist_len, w, h);
  137             h = opt.limit_h;
  138         }
  139     } else if (opt.limit_h) {
  140         vertical = 1;
  141         h = opt.limit_h;
  142 
  143         index_calculate_width(fn, &w, h, &tot_thumb_h);
  144     }
  145 
  146     index_image_width = w;
  147     index_image_height = h + title_area_h;
  148     im_main = imlib_create_image(index_image_width, index_image_height);
  149 
  150     if (!im_main) {
  151         if (index_image_height >= 32768 || index_image_width >= 32768) {
  152             eprintf("Failed to create %dx%d pixels (%d MB) index image.\n"
  153                     "This is probably due to Imlib2 issues when dealing with images larger than 32k x 32k pixels.",
  154                     index_image_width, index_image_height, index_image_width * index_image_height * 4 / (1024*1024));
  155         } else {
  156             eprintf("Failed to create %dx%d pixels (%d MB) index image. Do you have enough RAM?",
  157                     index_image_width, index_image_height, index_image_width * index_image_height * 4 / (1024*1024));
  158         }
  159     }
  160 
  161     if (bg_im)
  162         gib_imlib_blend_image_onto_image(im_main, bg_im,
  163                          gib_imlib_image_has_alpha
  164                          (bg_im), 0, 0, bg_w, bg_h, 0, 0, w, h, 1, 0, 0);
  165     else if (trans_bg) {
  166         gib_imlib_image_fill_rectangle(im_main, 0, 0, w, h + title_area_h, 0, 0, 0, 0);
  167         gib_imlib_image_set_has_alpha(im_main, 1);
  168     } else {
  169         /* Colour the background */
  170         gib_imlib_image_fill_rectangle(im_main, 0, 0, w, h + title_area_h, 0, 0, 0, 255);
  171     }
  172 
  173     if (opt.display) {
  174         winwid = winwidget_create_from_image(im_main, WIN_TYPE_SINGLE);
  175         winwidget_rename(winwid, PACKAGE " [index mode]");
  176         winwidget_show(winwid);
  177     }
  178 
  179     for (l = filelist; l; l = l->next) {
  180         file = FEH_FILE(l->data);
  181         if (last) {
  182             filelist = feh_file_remove_from_list(filelist, last);
  183             last = NULL;
  184         }
  185         D(("About to load image %s\n", file->filename));
  186         if (feh_load_image(&im_temp, file) != 0) {
  187             if (opt.verbose)
  188                 feh_display_status('.');
  189             D(("Successfully loaded %s\n", file->filename));
  190             www = opt.thumb_w;
  191             hhh = opt.thumb_h;
  192             ww = gib_imlib_image_get_width(im_temp);
  193             hh = gib_imlib_image_get_height(im_temp);
  194             thumbnailcount++;
  195 
  196             if (opt.aspect) {
  197                 double ratio = 0.0;
  198 
  199                 /* Keep the aspect ratio for the thumbnail */
  200                 ratio = ((double) ww / hh) / ((double) www / hhh);
  201 
  202                 if (ratio > 1.0)
  203                     hhh = opt.thumb_h / ratio;
  204                 else if (ratio != 1.0)
  205                     www = opt.thumb_w * ratio;
  206             }
  207 
  208             if ((!opt.stretch) && ((www > ww) || (hhh > hh))) {
  209                 /* Don't make the image larger unless stretch is specified */
  210                 www = ww;
  211                 hhh = hh;
  212             }
  213 
  214             im_thumb = gib_imlib_create_cropped_scaled_image(im_temp, 0, 0, ww, hh, www, hhh, 1);
  215             gib_imlib_free_image_and_decache(im_temp);
  216 
  217             if (opt.alpha) {
  218                 DATA8 atab[256];
  219 
  220                 D(("Applying alpha options\n"));
  221                 gib_imlib_image_set_has_alpha(im_thumb, 1);
  222                 memset(atab, opt.alpha_level, sizeof(atab));
  223                 gib_imlib_apply_color_modifier_to_rectangle
  224                     (im_thumb, 0, 0, www, hhh, NULL, NULL, NULL, atab);
  225             }
  226 
  227             text_area_w = opt.thumb_w;
  228             /* Now draw on the info text */
  229             if (opt.index_info) {
  230                 get_index_string_dim(file, fn, &fw, &fh);
  231                 if (fw > text_area_w)
  232                     text_area_w = fw;
  233             }
  234             if (text_area_w > opt.thumb_w)
  235                 text_area_w += 5;
  236 
  237             if (vertical) {
  238                 if (text_area_w > max_column_w)
  239                     max_column_w = text_area_w;
  240                 if (y > h - tot_thumb_h) {
  241                     y = 0;
  242                     x += max_column_w;
  243                     max_column_w = 0;
  244                 }
  245                 if (x > w - text_area_w)
  246                     break;
  247             } else {
  248                 if (x > w - text_area_w) {
  249                     x = 0;
  250                     y += tot_thumb_h;
  251                 }
  252                 if (y > h - tot_thumb_h)
  253                     break;
  254             }
  255 
  256             /* center image relative to the text below it (if any) */
  257             xxx = x + ((text_area_w - www) / 2);
  258             yyy = y;
  259 
  260             if (opt.aspect)
  261                 yyy += (opt.thumb_h - hhh) / 2;
  262 
  263             /* Draw now */
  264             gib_imlib_blend_image_onto_image(im_main, im_thumb,
  265                              gib_imlib_image_has_alpha
  266                              (im_thumb), 0, 0,
  267                              www, hhh, xxx,
  268                              yyy, www, hhh, 1, gib_imlib_image_has_alpha(im_thumb), 0);
  269 
  270             gib_imlib_free_image_and_decache(im_thumb);
  271 
  272             lineno = 0;
  273             if (opt.index_info) {
  274                 line = lines = feh_wrap_string(create_index_string(file),
  275                         opt.thumb_w * 3, fn, NULL);
  276 
  277                 while (line) {
  278                     gib_imlib_get_text_size(fn, (char *) line->data,
  279                             NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT);
  280                     gib_imlib_text_draw(im_main, fn, NULL,
  281                             x + ((text_area_w - fw) >> 1),
  282                             y + opt.thumb_h + (lineno++ * (th + 2)) + 2,
  283                             (char *) line->data,
  284                             IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);
  285                     line = line->next;
  286                 }
  287                 gib_list_free_and_data(lines);
  288             }
  289 
  290             if (vertical)
  291                 y += tot_thumb_h;
  292             else
  293                 x += text_area_w;
  294 
  295         } else {
  296             if (opt.verbose)
  297                 feh_display_status('x');
  298             last = l;
  299         }
  300         if (opt.display) {
  301             winwidget_render_image(winwid, 0, 0);
  302             if (!feh_main_iteration(0))
  303                 exit(0);
  304         }
  305     }
  306     if (opt.verbose)
  307         putc('\n', stderr);
  308 
  309     if (opt.title_font) {
  310         int fw, fh, fx, fy;
  311         char *s;
  312 
  313         s = create_index_title_string(thumbnailcount, w, h);
  314         gib_imlib_get_text_size(title_fn, s, NULL, &fw, &fh, IMLIB_TEXT_TO_RIGHT);
  315         fx = (index_image_width - fw) >> 1;
  316         fy = index_image_height - fh - 2;
  317         gib_imlib_text_draw(im_main, title_fn, NULL, fx, fy, s, IMLIB_TEXT_TO_RIGHT, 255, 255, 255, 255);
  318 
  319         if (opt.display)
  320             winwidget_render_image(winwid, 0, 0);
  321     }
  322 
  323     if (opt.output && opt.output_file) {
  324         char output_buf[1024];
  325 
  326         if (opt.output_dir)
  327             snprintf(output_buf, 1024, "%s/%s", opt.output_dir, opt.output_file);
  328         else {
  329             strncpy(output_buf, opt.output_file, 1023);
  330             output_buf[1023] = '\0';
  331         }
  332 
  333         gib_imlib_save_image_with_error_return(im_main, output_buf, &err);
  334         if (err) {
  335             feh_imlib_print_load_error(output_buf, im_main, err);
  336         }
  337         else if (opt.verbose) {
  338             int tw, th;
  339 
  340             tw = gib_imlib_image_get_width(im_main);
  341             th = gib_imlib_image_get_height(im_main);
  342             fprintf(stderr, PACKAGE " - File saved as %s\n", output_buf);
  343             fprintf(stderr,
  344                 "    - Image is %dx%d pixels and contains %d thumbnails\n", tw, th, thumbnailcount);
  345         }
  346     }
  347 
  348     if (!opt.display)
  349         gib_imlib_free_image_and_decache(im_main);
  350 
  351     return;
  352 }
  353 
  354 void index_calculate_height(Imlib_Font fn, int w, int *h, int *tot_thumb_h)
  355 {
  356     gib_list *l;
  357     feh_file *file = NULL;
  358     int x = 0, y = 0;
  359     int fw = 0, fh = 0;
  360     int text_area_w = 0, text_area_h = 0;
  361 
  362     for (l = filelist; l; l = l->next) {
  363         file = FEH_FILE(l->data);
  364         text_area_w = opt.thumb_w;
  365         if (opt.index_info) {
  366             get_index_string_dim(file, fn, &fw, &fh);
  367             if (fw > text_area_w)
  368                 text_area_w = fw;
  369             if (fh > text_area_h) {
  370                 text_area_h = fh + 5;
  371                 *tot_thumb_h = opt.thumb_h + text_area_h;
  372             }
  373         }
  374 
  375         if (text_area_w > opt.thumb_w)
  376             text_area_w += 5;
  377 
  378         if ((x > w - text_area_w)) {
  379             x = 0;
  380             y += *tot_thumb_h;
  381         }
  382 
  383         x += text_area_w;
  384     }
  385     *h = y + *tot_thumb_h;
  386 }
  387 
  388 void index_calculate_width(Imlib_Font fn, int *w, int h, int *tot_thumb_h)
  389 {
  390     gib_list *l;
  391     feh_file *file = NULL;
  392     int x = 0, y = 0;
  393     int fw = 0, fh = 0;
  394     int text_area_w = 0, text_area_h = 0;
  395     int max_column_w = 0;
  396 
  397     for (l = filelist; l; l = l->next) {
  398         file = FEH_FILE(l->data);
  399         text_area_w = opt.thumb_w;
  400         /* Calc width of text */
  401         if (opt.index_info) {
  402             get_index_string_dim(file, fn, &fw, &fh);
  403             if (fw > text_area_w)
  404                 text_area_w = fw;
  405             if (fh > text_area_h) {
  406                 text_area_h = fh + 5;
  407                 *tot_thumb_h = opt.thumb_h + text_area_h;
  408             }
  409         }
  410         if (text_area_w > opt.thumb_w)
  411             text_area_w += 5;
  412 
  413         if (text_area_w > max_column_w)
  414             max_column_w = text_area_w;
  415 
  416         if ((y > h - *tot_thumb_h)) {
  417             y = 0;
  418             x += max_column_w;
  419             max_column_w = 0;
  420         }
  421 
  422         y += *tot_thumb_h;
  423     }
  424     *w = x + text_area_w;
  425 }
  426 
  427 void get_index_string_dim(feh_file *file, Imlib_Font fn, int *fw, int *fh)
  428 {
  429     int line_w, line_h;
  430     char fake_file = 0;
  431     gib_list *line, *lines;
  432     int max_w = 0, total_h = 0;
  433 
  434     if (!opt.index_info) {
  435         *fw = 0;
  436         *fh = 0;
  437         return;
  438     }
  439 
  440     /* called with file = NULL in the setup phase.
  441      * We need a fake file, otherwise feh_printf will remove format specifiers,
  442      * leading e.g. to a 0x0 report for index_dim = "%n".
  443      */
  444     if (file == NULL) {
  445         fake_file = 1;
  446         file = feh_file_new("foo");
  447         file->info = feh_file_info_new();
  448     }
  449 
  450     line = lines = feh_wrap_string(create_index_string(file), opt.thumb_w * 3, fn, NULL);
  451 
  452     while (line) {
  453         gib_imlib_get_text_size(fn, (char *) line->data,
  454             NULL, &line_w, &line_h, IMLIB_TEXT_TO_RIGHT);
  455 
  456         if (line_w > max_w)
  457             max_w = line_w;
  458         total_h += line_h + 2;
  459 
  460         line = line->next;
  461     }
  462 
  463     gib_list_free_and_data(lines);
  464     if (fake_file)
  465         feh_file_free(file);
  466 
  467     *fw = max_w;
  468     *fh = total_h;
  469     return;
  470 }
  471 
  472 char *create_index_string(feh_file * file)
  473 {
  474     return feh_printf(opt.index_info, file, NULL);
  475 }
  476 
  477 char *create_index_title_string(int num, int w, int h)
  478 {
  479     static char str[50];
  480 
  481     snprintf(str, sizeof(str), PACKAGE " index - %d thumbnails, %d by %d pixels", num, w, h);
  482     return(str);
  483 }