2009-05-08 20:42:34 +00:00
/* Conky, a system monitor, based on torsmo
*
* Please see COPYING for details
*
* Copyright ( c ) 2005 - 2009 Brenden Matthews , et . al .
* All rights reserved .
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*
*/
# include "imlib2.h"
# include "config.h"
# include "logging.h"
2009-05-25 04:33:47 +00:00
# include "common.h"
2009-05-08 20:42:34 +00:00
# include <Imlib2.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
2009-05-24 19:47:44 +00:00
# include <limits.h>
2009-06-03 19:24:53 +00:00
# include <time.h>
2009-05-08 20:42:34 +00:00
struct image_list_s {
2009-05-20 04:49:42 +00:00
char name [ DEFAULT_TEXT_BUFFER_SIZE ] ;
2009-05-08 20:42:34 +00:00
Imlib_Image image ;
2009-05-17 05:47:02 +00:00
int x , y , w , h ;
int wh_set ;
2009-06-03 19:24:53 +00:00
char no_cache ;
int flush_interval ;
int flush_last ;
2009-05-08 20:42:34 +00:00
struct image_list_s * next ;
} ;
struct image_list_s * image_list_start , * image_list_end ;
/* areas to update */
Imlib_Updates updates , current_update ;
/* our virtual framebuffer image we draw into */
Imlib_Image buffer , image ;
2009-05-22 17:23:05 +00:00
static int cache_size_set = 0 ;
2009-06-03 19:24:53 +00:00
/* flush the image cache ever X seconds */
static int cimlib_cache_flush_interval = 0 ;
static int cimlib_cache_flush_last = 0 ;
2009-05-08 20:42:34 +00:00
# define DEFAULT_CACHE_SIZE 4096 * 1024 /* default cache size for loaded images */
void cimlib_set_cache_size ( long size )
{
2009-05-17 05:47:02 +00:00
imlib_set_cache_size ( size ) ;
2009-05-22 17:23:05 +00:00
cache_size_set = 1 ;
2009-05-08 20:42:34 +00:00
}
2009-06-03 19:24:53 +00:00
void cimlib_set_cache_flush_interval ( long interval )
{
cimlib_cache_flush_interval = interval ;
}
2009-05-08 20:42:34 +00:00
void cimlib_cleanup ( void )
{
struct image_list_s * cur = image_list_start , * last = NULL ;
while ( cur ) {
last = cur ;
cur = last - > next ;
free ( last ) ;
}
image_list_start = image_list_end = NULL ;
}
2009-05-17 05:47:02 +00:00
void cimlib_init ( Display * display , Window drawable , Visual * visual , Colormap colourmap )
2009-05-08 20:42:34 +00:00
{
image_list_start = image_list_end = NULL ;
2009-05-22 17:23:05 +00:00
if ( ! cache_size_set ) cimlib_set_cache_size ( DEFAULT_CACHE_SIZE ) ;
2009-05-08 20:42:34 +00:00
/* set the maximum number of colors to allocate for 8bpp and less to 256 */
imlib_set_color_usage ( 256 ) ;
/* dither for depths < 24bpp */
imlib_context_set_dither ( 1 ) ;
/* set the display , visual, colormap and drawable we are using */
imlib_context_set_display ( display ) ;
imlib_context_set_visual ( visual ) ;
imlib_context_set_colormap ( colourmap ) ;
2009-05-17 05:47:02 +00:00
imlib_context_set_drawable ( drawable ) ;
2009-05-08 20:42:34 +00:00
}
2009-05-17 05:47:02 +00:00
void cimlib_add_image ( const char * args )
2009-05-08 20:42:34 +00:00
{
struct image_list_s * cur = NULL ;
2009-05-17 05:47:02 +00:00
char * tmp ;
2009-05-08 20:42:34 +00:00
cur = malloc ( sizeof ( struct image_list_s ) ) ;
memset ( cur , 0 , sizeof ( struct image_list_s ) ) ;
2009-05-17 05:47:02 +00:00
if ( ! sscanf ( args , " %1024s " , cur - > name ) ) {
2009-06-03 19:24:53 +00:00
ERR ( " Invalid args for $image. Format is: '<path to image> (-p x,y) (-s WxH) (-n) (-f interval)' (got '%s') " , args ) ;
2009-05-17 05:47:02 +00:00
}
2009-05-25 04:33:47 +00:00
to_real_path ( cur - > name , cur - > name ) ;
2009-05-17 05:47:02 +00:00
// now we check for optional args
tmp = strstr ( args , " -p " ) ;
if ( tmp ) {
tmp + = 3 ;
sscanf ( tmp , " %i,%i " , & cur - > x , & cur - > y ) ;
}
tmp = strstr ( args , " -s " ) ;
if ( tmp ) {
tmp + = 3 ;
if ( sscanf ( tmp , " %ix%i " , & cur - > w , & cur - > h ) ) {
cur - > wh_set = 1 ;
}
}
2009-06-03 19:24:53 +00:00
tmp = strstr ( args , " -n " ) ;
if ( tmp ) {
cur - > no_cache = 1 ;
}
tmp = strstr ( args , " -f " ) ;
if ( tmp ) {
tmp + = 3 ;
if ( sscanf ( tmp , " %d " , & cur - > flush_interval ) ) {
cur - > no_cache = 0 ;
}
}
2009-05-08 20:42:34 +00:00
if ( image_list_end ) {
image_list_end - > next = cur ;
image_list_end = cur ;
} else {
image_list_start = image_list_end = cur ;
}
}
2009-05-24 22:52:48 +00:00
static void cimlib_draw_image ( struct image_list_s * cur , int * clip_x , int * clip_y , int * clip_x2 , int * clip_y2 )
2009-05-08 20:42:34 +00:00
{
image = imlib_load_image ( cur - > name ) ;
if ( image ) {
int w , h ;
2009-06-03 19:24:53 +00:00
time_t now = time ( NULL ) ;
DBGP ( " Drawing image '%s' at (%i,%i) scaled to %ix%i, caching interval set to %i (with -n opt %i) " , cur - > name , cur - > x , cur - > y , cur - > w , cur - > h , cur - > flush_interval , cur - > no_cache ) ;
2009-05-08 20:42:34 +00:00
imlib_context_set_image ( image ) ;
2009-05-24 22:52:48 +00:00
/* turn alpha channel on */
imlib_image_set_has_alpha ( 1 ) ;
2009-05-08 20:42:34 +00:00
w = imlib_image_get_width ( ) ;
h = imlib_image_get_height ( ) ;
2009-05-22 07:18:07 +00:00
if ( ! cur - > wh_set ) {
cur - > w = w ;
cur - > h = h ;
}
2009-05-08 20:42:34 +00:00
imlib_context_set_image ( buffer ) ;
2009-05-22 07:39:38 +00:00
imlib_blend_image_onto_image ( image , 1 , 0 , 0 , w , h ,
2009-05-17 05:47:02 +00:00
cur - > x , cur - > y , cur - > w , cur - > h ) ;
2009-05-08 20:42:34 +00:00
imlib_context_set_image ( image ) ;
2009-06-03 19:24:53 +00:00
if ( cur - > no_cache | | ( cur - > flush_interval & & now - cur - > flush_interval > cur - > flush_last ) ) {
imlib_free_image_and_decache ( ) ;
cur - > flush_last = now ;
} else {
imlib_free_image ( ) ;
}
2009-05-24 19:47:44 +00:00
if ( cur - > x < * clip_x ) * clip_x = cur - > x ;
if ( cur - > y < * clip_y ) * clip_y = cur - > y ;
2009-05-24 22:52:48 +00:00
if ( cur - > x + cur - > w > * clip_x2 ) * clip_x2 = cur - > x + cur - > w ;
if ( cur - > y + cur - > h > * clip_y2 ) * clip_y2 = cur - > y + cur - > h ;
2009-05-08 20:42:34 +00:00
} else {
ERR ( " Unable to load image '%s' " , cur - > name ) ;
}
}
2009-05-24 22:52:48 +00:00
static void cimlib_draw_all ( int * clip_x , int * clip_y , int * clip_x2 , int * clip_y2 )
2009-05-08 20:42:34 +00:00
{
struct image_list_s * cur = image_list_start ;
while ( cur ) {
2009-05-24 22:52:48 +00:00
cimlib_draw_image ( cur , clip_x , clip_y , clip_x2 , clip_y2 ) ;
2009-05-08 20:42:34 +00:00
cur = cur - > next ;
}
}
2009-05-18 05:11:22 +00:00
void cimlib_render ( int x , int y , int width , int height )
2009-05-08 20:42:34 +00:00
{
2009-05-24 19:47:44 +00:00
int clip_x = INT_MAX , clip_y = INT_MAX ;
2009-05-24 22:52:48 +00:00
int clip_x2 = 0 , clip_y2 = 0 ;
2009-06-03 19:24:53 +00:00
time_t now ;
2009-05-24 19:47:44 +00:00
2009-05-08 20:42:34 +00:00
if ( ! image_list_start ) return ; /* are we actually drawing anything? */
2009-06-03 19:24:53 +00:00
/* cheque if it's time to flush our cache */
now = time ( NULL ) ;
if ( cimlib_cache_flush_interval & & now - cimlib_cache_flush_interval > cimlib_cache_flush_last ) {
2009-06-03 19:31:16 +00:00
int size = imlib_get_cache_size ( ) ;
imlib_set_cache_size ( 0 ) ;
imlib_set_cache_size ( size ) ;
2009-06-03 19:24:53 +00:00
cimlib_cache_flush_last = now ;
DBGP ( " Flushing Imlib2 cache (%li) \n " , now ) ;
}
2009-05-08 20:42:34 +00:00
/* take all the little rectangles to redraw and merge them into
* something sane for rendering */
2009-05-17 05:47:02 +00:00
buffer = imlib_create_image ( width , height ) ;
2009-05-18 05:11:22 +00:00
/* clear our buffer */
imlib_context_set_image ( buffer ) ;
imlib_image_clear ( ) ;
2009-05-17 05:47:02 +00:00
/* we can blend stuff now */
imlib_context_set_blend ( 1 ) ;
2009-05-24 22:52:48 +00:00
/* turn alpha channel on */
imlib_image_set_has_alpha ( 1 ) ;
2009-05-17 05:47:02 +00:00
2009-05-24 22:52:48 +00:00
cimlib_draw_all ( & clip_x , & clip_y , & clip_x2 , & clip_y2 ) ;
2009-05-17 05:47:02 +00:00
/* set the buffer image as our current image */
imlib_context_set_image ( buffer ) ;
2009-05-24 19:47:44 +00:00
/* setup our clip rect */
if ( clip_x = = INT_MAX ) clip_x = 0 ;
if ( clip_y = = INT_MAX ) clip_y = 0 ;
2009-05-17 05:47:02 +00:00
/* render the image at 0, 0 */
2009-05-24 22:52:48 +00:00
imlib_render_image_part_on_drawable_at_size ( clip_x , clip_y , clip_x2 - clip_x ,
clip_y2 - clip_y , x + clip_x , y + clip_y , clip_x2 - clip_x ,
clip_y2 - clip_y ) ;
2009-05-17 05:47:02 +00:00
/* don't need that temporary buffer image anymore */
imlib_free_image ( ) ;
2009-05-08 20:42:34 +00:00
}