| @@ -17,6 +17,7 @@ |
| 17 | 17 | | */ |
| 18 | 18 | | |
| 19 | 19 | | #define _POSIX_C_SOURCE 200112L |
| 20 | + | #define _IMAGE_CONFIG |
| 20 | 21 | | |
| 21 | 22 | | #include <string.h> |
| 22 | 23 | | #include <unistd.h> |
| @@ -34,10 +35,10 @@ |
| 34 | 35 | | #include "image.h" |
| 35 | 36 | | #include "options.h" |
| 36 | 37 | | #include "util.h" |
| 37 | | − | |
| 38 | | − | #define _IMAGE_CONFIG |
| 39 | 38 | | #include "config.h" |
| 40 | 39 | | |
| 40 | + | #define ZOOMDIFF(z1,z2) ((z1) - (z2) > 0.001 || (z1) - (z2) < -0.001) |
| 41 | + | |
| 41 | 42 | | enum { MIN_GIF_DELAY = 50 }; |
| 42 | 43 | | |
| 43 | 44 | | float zoom_min; |
| @@ -54,6 +55,8 @@ void img_init(img_t *img, win_t *win) { |
| 54 | 55 | | img->zoom = options->zoom; |
| 55 | 56 | | img->zoom = MAX(img->zoom, zoom_min); |
| 56 | 57 | | img->zoom = MIN(img->zoom, zoom_max); |
| 58 | + | img->checkpan = 0; |
| 59 | + | img->dirty = 0; |
| 57 | 60 | | img->aa = options->aa; |
| 58 | 61 | | img->alpha = 1; |
| 59 | 62 | | img->slideshow = 0; |
| @@ -313,6 +316,7 @@ int img_load(img_t *img, const fileinfo_t *file) { |
| 313 | 316 | | img->w = imlib_image_get_width(); |
| 314 | 317 | | img->h = imlib_image_get_height(); |
| 315 | 318 | | |
| 319 | + | img->dirty = 1; |
| 316 | 320 | | return 1; |
| 317 | 321 | | } |
| 318 | 322 | | |
| @@ -339,10 +343,15 @@ void img_close(img_t *img, int decache) { |
| 339 | 343 | | } |
| 340 | 344 | | } |
| 341 | 345 | | |
| 342 | | − | void img_check_pan(img_t *img, win_t *win) { |
| 346 | + | void img_check_pan(img_t *img, win_t *win, int moved) { |
| 347 | + | int ox, oy; |
| 348 | + | |
| 343 | 349 | | if (!img || !win) |
| 344 | 350 | | return; |
| 345 | 351 | | |
| 352 | + | ox = img->x; |
| 353 | + | oy = img->y; |
| 354 | + | |
| 346 | 355 | | if (img->w * img->zoom > win->w) { |
| 347 | 356 | | if (img->x > 0 && img->x + img->w * img->zoom > win->w) |
| 348 | 357 | | img->x = 0; |
| @@ -359,23 +368,32 @@ void img_check_pan(img_t *img, win_t *win) { |
| 359 | 368 | | } else { |
| 360 | 369 | | img->y = (win->h - img->h * img->zoom) / 2; |
| 361 | 370 | | } |
| 371 | + | |
| 372 | + | if (!moved && (ox != img->x || oy != img->y)) |
| 373 | + | img->dirty = 1; |
| 362 | 374 | | } |
| 363 | 375 | | |
| 364 | 376 | | int img_fit(img_t *img, win_t *win) { |
| 365 | | − | float oz, zw, zh; |
| 377 | + | float z, zmax, zw, zh; |
| 366 | 378 | | |
| 367 | | − | if (!img || !win) |
| 379 | + | if (!img || !win || img->scalemode == SCALE_ZOOM) |
| 368 | 380 | | return 0; |
| 369 | 381 | | |
| 370 | | − | oz = img->zoom; |
| 382 | + | zmax = img->scalemode == SCALE_DOWN ? 1.0 : zoom_max; |
| 371 | 383 | | zw = (float) win->w / (float) img->w; |
| 372 | 384 | | zh = (float) win->h / (float) img->h; |
| 373 | 385 | | |
| 374 | | − | img->zoom = MIN(zw, zh); |
| 375 | | − | img->zoom = MAX(img->zoom, zoom_min); |
| 376 | | − | img->zoom = MIN(img->zoom, zoom_max); |
| 386 | + | z = MIN(zw, zh); |
| 387 | + | z = MAX(z, zoom_min); |
| 388 | + | z = MIN(z, zmax); |
| 377 | 389 | | |
| 378 | | − | return oz != img->zoom; |
| 390 | + | if (ZOOMDIFF(z, img->zoom)) { |
| 391 | + | img->zoom = z; |
| 392 | + | img->dirty = 1; |
| 393 | + | return 1; |
| 394 | + | } else { |
| 395 | + | return 0; |
| 396 | + | } |
| 379 | 397 | | } |
| 380 | 398 | | |
| 381 | 399 | | void img_render(img_t *img, win_t *win) { |
| @@ -385,11 +403,7 @@ void img_render(img_t *img, win_t *win) { |
| 385 | 403 | | if (!img || !img->im || !win) |
| 386 | 404 | | return; |
| 387 | 405 | | |
| 388 | | − | if (img->scalemode != SCALE_ZOOM) { |
| 389 | | − | img_fit(img, win); |
| 390 | | − | if (img->scalemode == SCALE_DOWN && img->zoom > 1.0) |
| 391 | | − | img->zoom = 1.0; |
| 392 | | − | } |
| 406 | + | img_fit(img, win); |
| 393 | 407 | | |
| 394 | 408 | | if (!img->re) { |
| 395 | 409 | | /* rendered for the first time */ |
| @@ -405,10 +419,13 @@ void img_render(img_t *img, win_t *win) { |
| 405 | 419 | | } |
| 406 | 420 | | |
| 407 | 421 | | if (img->checkpan) { |
| 408 | | − | img_check_pan(img, win); |
| 422 | + | img_check_pan(img, win, 0); |
| 409 | 423 | | img->checkpan = 0; |
| 410 | 424 | | } |
| 411 | 425 | | |
| 426 | + | if (!img->dirty) |
| 427 | + | return; |
| 428 | + | |
| 412 | 429 | | /* calculate source and destination offsets */ |
| 413 | 430 | | if (img->x < 0) { |
| 414 | 431 | | sx = -img->x / img->zoom; |
| @@ -444,6 +461,8 @@ void img_render(img_t *img, win_t *win) { |
| 444 | 461 | | imlib_render_image_part_on_drawable_at_size(sx, sy, sw, sh, dx, dy, dw, dh); |
| 445 | 462 | | |
| 446 | 463 | | win_draw(win); |
| 464 | + | |
| 465 | + | img->dirty = 0; |
| 447 | 466 | | } |
| 448 | 467 | | |
| 449 | 468 | | int img_fit_win(img_t *img, win_t *win) { |
| @@ -466,7 +485,12 @@ int img_center(img_t *img, win_t *win) { |
| 466 | 485 | | img->x = (win->w - img->w * img->zoom) / 2; |
| 467 | 486 | | img->y = (win->h - img->h * img->zoom) / 2; |
| 468 | 487 | | |
| 469 | | − | return ox != img->x || oy != img->y; |
| 488 | + | if (ox != img->x || oy != img->y) { |
| 489 | + | img->dirty = 1; |
| 490 | + | return 1; |
| 491 | + | } else { |
| 492 | + | return 0; |
| 493 | + | } |
| 470 | 494 | | } |
| 471 | 495 | | |
| 472 | 496 | | int img_zoom(img_t *img, win_t *win, float z) { |
| @@ -478,11 +502,12 @@ int img_zoom(img_t *img, win_t *win, float z) { |
| 478 | 502 | | |
| 479 | 503 | | img->scalemode = SCALE_ZOOM; |
| 480 | 504 | | |
| 481 | | − | if (z != img->zoom) { |
| 505 | + | if (ZOOMDIFF(z, img->zoom)) { |
| 482 | 506 | | img->x = win->w / 2 - (win->w / 2 - img->x) * z / img->zoom; |
| 483 | 507 | | img->y = win->h / 2 - (win->h / 2 - img->y) * z / img->zoom; |
| 484 | 508 | | img->zoom = z; |
| 485 | 509 | | img->checkpan = 1; |
| 510 | + | img->dirty = 1; |
| 486 | 511 | | return 1; |
| 487 | 512 | | } else { |
| 488 | 513 | | return 0; |
| @@ -527,9 +552,14 @@ int img_move(img_t *img, win_t *win, int dx, int dy) { |
| 527 | 552 | | img->x += dx; |
| 528 | 553 | | img->y += dy; |
| 529 | 554 | | |
| 530 | | − | img_check_pan(img, win); |
| 555 | + | img_check_pan(img, win, 1); |
| 531 | 556 | | |
| 532 | | − | return ox != img->x || oy != img->y; |
| 557 | + | if (ox != img->x || oy != img->y) { |
| 558 | + | img->dirty = 1; |
| 559 | + | return 1; |
| 560 | + | } else { |
| 561 | + | return 0; |
| 562 | + | } |
| 533 | 563 | | } |
| 534 | 564 | | |
| 535 | 565 | | int img_pan(img_t *img, win_t *win, direction_t dir, int screen) { |
| @@ -546,7 +576,6 @@ int img_pan(img_t *img, win_t *win, direction_t dir, int screen) { |
| 546 | 576 | | case DIR_DOWN: |
| 547 | 577 | | return img_move(img, win, 0, win->h / (screen ? 1 : 5) * -1); |
| 548 | 578 | | } |
| 549 | | − | |
| 550 | 579 | | return 0; |
| 551 | 580 | | } |
| 552 | 581 | | |
| @@ -574,9 +603,14 @@ int img_pan_edge(img_t *img, win_t *win, direction_t dir) { |
| 574 | 603 | | break; |
| 575 | 604 | | } |
| 576 | 605 | | |
| 577 | | − | img_check_pan(img, win); |
| 606 | + | img_check_pan(img, win, 1); |
| 578 | 607 | | |
| 579 | | − | return ox != img->x || oy != img->y; |
| 608 | + | if (ox != img->x || oy != img->y) { |
| 609 | + | img->dirty = 1; |
| 610 | + | return 1; |
| 611 | + | } else { |
| 612 | + | return 0; |
| 613 | + | } |
| 580 | 614 | | } |
| 581 | 615 | | |
| 582 | 616 | | void img_rotate(img_t *img, win_t *win, int d) { |
| @@ -599,6 +633,7 @@ void img_rotate(img_t *img, win_t *win, int d) { |
| 599 | 633 | | img->h = tmp; |
| 600 | 634 | | |
| 601 | 635 | | img->checkpan = 1; |
| 636 | + | img->dirty = 1; |
| 602 | 637 | | } |
| 603 | 638 | | |
| 604 | 639 | | void img_rotate_left(img_t *img, win_t *win) { |
| @@ -610,11 +645,13 @@ void img_rotate_right(img_t *img, win_t *win) { |
| 610 | 645 | | } |
| 611 | 646 | | |
| 612 | 647 | | void img_toggle_antialias(img_t *img) { |
| 613 | | − | if (img && img->im) { |
| 614 | | − | img->aa ^= 1; |
| 615 | | − | imlib_context_set_image(img->im); |
| 616 | | − | imlib_context_set_anti_alias(img->aa); |
| 617 | | − | } |
| 648 | + | if (!img || !img->im) |
| 649 | + | return; |
| 650 | + | |
| 651 | + | img->aa ^= 1; |
| 652 | + | imlib_context_set_image(img->im); |
| 653 | + | imlib_context_set_anti_alias(img->aa); |
| 654 | + | img->dirty = 1; |
| 618 | 655 | | } |
| 619 | 656 | | |
| 620 | 657 | | int img_frame_goto(img_t *img, int n) { |
| @@ -631,6 +668,7 @@ int img_frame_goto(img_t *img, int n) { |
| 631 | 668 | | img->w = imlib_image_get_width(); |
| 632 | 669 | | img->h = imlib_image_get_height(); |
| 633 | 670 | | img->checkpan = 1; |
| 671 | + | img->dirty = 1; |
| 634 | 672 | | |
| 635 | 673 | | return 1; |
| 636 | 674 | | } |
| @@ -664,5 +702,6 @@ int img_frame_animate(img_t *img, int restart) { |
| 664 | 702 | | } |
| 665 | 703 | | img->multi.animate = 1; |
| 666 | 704 | | |
| 705 | + | img->dirty = 1; |
| 667 | 706 | | return img->multi.frames[img->multi.sel].delay; |
| 668 | 707 | | } |