00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #define LOCAL_DEBUG
00021 #undef DO_CLOCKING
00022 #ifndef NO_DEBUG_OUTPUT
00023 #undef DEBUG_RECTS
00024 #undef DEBUG_RECTS2
00025 #endif
00026
00027 #ifdef _WIN32
00028 #include "win32/config.h"
00029 #else
00030 #include "config.h"
00031 #endif
00032
00033
00034 #define USE_64BIT_FPU
00035
00036 #include <string.h>
00037 #ifdef DO_CLOCKING
00038 #if TIME_WITH_SYS_TIME
00039 # include <sys/time.h>
00040 # include <time.h>
00041 #else
00042 # if HAVE_SYS_TIME_H
00043 # include <sys/time.h>
00044 # else
00045 # include <time.h>
00046 # endif
00047 #endif
00048 #endif
00049 #ifdef HAVE_UNISTD_H
00050 #include <unistd.h>
00051 #endif
00052 #ifdef HAVE_STDLIB_H
00053 #include <stdlib.h>
00054 #endif
00055 #ifdef HAVE_STDARG_H
00056 #include <stdarg.h>
00057 #endif
00058
00059 #ifdef _WIN32
00060 # include "win32/afterbase.h"
00061 #else
00062 # include "afterbase.h"
00063 #endif
00064 #include "asvisual.h"
00065 #include "scanline.h"
00066 #include "blender.h"
00067 #include "asimage.h"
00068 #include "ascmap.h"
00069
00070 static ASVisual __as_dummy_asvisual = {0};
00071 static ASVisual *__as_default_asvisual = &__as_dummy_asvisual ;
00072
00073
00074 ASVisual *_set_default_asvisual( ASVisual *new_v )
00075 {
00076 ASVisual *old_v = __as_default_asvisual ;
00077 __as_default_asvisual = new_v?new_v:&__as_dummy_asvisual ;
00078
00079
00080
00081
00082
00083
00084 return old_v;
00085 }
00086
00087 ASVisual *get_default_asvisual()
00088 {
00089 return __as_default_asvisual?__as_default_asvisual:&__as_dummy_asvisual;
00090 }
00091
00092
00093
00094 static CARD8 *__as_compression_buffer = NULL ;
00095 static size_t __as_compression_buffer_len = 0;
00096
00097 static inline CARD8* get_compression_buffer( size_t size )
00098 {
00099 if( size > __as_compression_buffer_len )
00100 __as_compression_buffer_len = (size+1023)&(~0x03FF) ;
00101 return (__as_compression_buffer = realloc( __as_compression_buffer, __as_compression_buffer_len ));
00102 }
00103
00104 static inline void release_compression_buffer( CARD8 *ptr )
00105 {
00106
00107 }
00108
00109
00110
00111 #ifdef TRACK_ASIMAGES
00112 static ASHashTable *__as_image_registry = NULL ;
00113 #endif
00114
00115 #ifdef HAVE_MMX
00116 Bool asimage_use_mmx = True;
00117 #else
00118 Bool asimage_use_mmx = False;
00119 #endif
00120
00121
00122 void
00123 asimage_init (ASImage * im, Bool free_resources)
00124 {
00125 if (im != NULL)
00126 {
00127 if (free_resources)
00128 {
00129 register int i ;
00130 for( i = im->height*4-1 ; i>= 0 ; --i )
00131 if( im->red[i] != 0 )
00132 forget_data( NULL, im->red[i] );
00133 if( im->red )
00134 free(im->red);
00135 #ifndef X_DISPLAY_MISSING
00136 if( im->alt.ximage )
00137 XDestroyImage( im->alt.ximage );
00138 if( im->alt.mask_ximage )
00139 XDestroyImage( im->alt.mask_ximage );
00140 #endif
00141 if( im->alt.argb32 )
00142 free( im->alt.argb32 );
00143 if( im->alt.vector )
00144 free( im->alt.vector );
00145 if( im->name )
00146 free( im->name );
00147 }
00148 memset (im, 0x00, sizeof (ASImage));
00149 im->magic = MAGIC_ASIMAGE ;
00150 im->back_color = ARGB32_DEFAULT_BACK_COLOR ;
00151 }
00152 }
00153
00154 void
00155 flush_asimage_cache( ASImage *im )
00156 {
00157 #ifndef X_DISPLAY_MISSING
00158 if( im->alt.ximage )
00159 {
00160 XDestroyImage( im->alt.ximage );
00161 im->alt.ximage = NULL ;
00162 }
00163 if( im->alt.mask_ximage )
00164 {
00165 XDestroyImage( im->alt.mask_ximage );
00166 im->alt.mask_ximage = NULL ;
00167 }
00168 #endif
00169 }
00170
00171 static void
00172 alloc_asimage_channels ( ASImage *im )
00173 {
00174
00175 im->red = safecalloc (1, sizeof (ASStorageID) * im->height * 4);
00176 LOCAL_DEBUG_OUT( "allocated %p for channels of the image %p", im->red, im );
00177 if( im->red == NULL )
00178 {
00179 show_error( "Insufficient memory to create image %dx%d!", im->width, im->height );
00180 return ;
00181 }
00182
00183 im->green = im->red+im->height;
00184 im->blue = im->red+(im->height*2);
00185 im->alpha = im->red+(im->height*3);
00186 im->channels[IC_RED] = im->red ;
00187 im->channels[IC_GREEN] = im->green ;
00188 im->channels[IC_BLUE] = im->blue ;
00189 im->channels[IC_ALPHA] = im->alpha ;
00190 }
00191
00192 void
00193 asimage_start (ASImage * im, unsigned int width, unsigned int height, unsigned int compression)
00194 {
00195 if (im)
00196 {
00197 asimage_init (im, True);
00198 im->height = height;
00199 im->width = width;
00200
00201 alloc_asimage_channels( im );
00202
00203 if( compression == 0 )
00204 set_flags( im->flags, ASIM_NO_COMPRESSION );
00205 }
00206 }
00207
00208 Bool
00209 asimage_replace (ASImage *im, ASImage *from)
00210 {
00211 if ( im && from && im != from )
00212 if( im->magic == MAGIC_ASIMAGE && from->magic == MAGIC_ASIMAGE && from->imageman == NULL )
00213 {
00214 int ref_count = im->ref_count ;
00215 ASImageManager *imageman = im->imageman ;
00216 char *name = im->name ;
00217 ASFlagType saved_flags = im->flags & (ASIM_NAME_IS_FILENAME|ASIM_NO_COMPRESSION) ;
00218
00219 im->name = NULL ;
00220 asimage_init (im, True);
00221
00222 memcpy( im, from, sizeof(ASImage) );
00223
00224 memset( from, 0x00, sizeof(ASImage) );
00225
00226 im->ref_count = ref_count ;
00227 im->imageman = imageman ;
00228 im->name = name ;
00229 set_flags( im->flags, saved_flags );
00230
00231 return True ;
00232 }
00233 return False;
00234 }
00235
00236
00237 static ASImage*
00238 check_created_asimage( ASImage *im, unsigned int width, unsigned int height )
00239 {
00240 if( im->width == 0 || im->height == 0 )
00241 {
00242 free( im );
00243 im = NULL ;
00244 #ifdef TRACK_ASIMAGES
00245 show_error( "failed to create ASImage of size %dx%d", width, height );
00246 #endif
00247 }else
00248 {
00249 #ifdef TRACK_ASIMAGES
00250 show_progress( "created ASImage %p of size %dx%d (%s compressed )", im,
00251 width, height, (get_flags(im->flags, ASIM_NO_COMPRESSION)?" no":"") );
00252 if( __as_image_registry == NULL )
00253 __as_image_registry = create_ashash( 0, pointer_hash_value, NULL, NULL );
00254 add_hash_item( __as_image_registry, AS_HASHABLE(im), im );
00255 #endif
00256 }
00257 return im ;
00258 }
00259
00260 ASImage *
00261 create_asimage( unsigned int width, unsigned int height, unsigned int compression)
00262 {
00263 ASImage *im = safecalloc( 1, sizeof(ASImage) );
00264 asimage_start( im, width, height, compression );
00265 return check_created_asimage( im, width, height );
00266 }
00267
00268 void
00269 destroy_asimage( ASImage **im )
00270 {
00271 if( im )
00272 {
00273
00274 if( *im && !AS_ASSERT_NOTVAL((*im)->imageman,NULL))
00275 {
00276 #ifdef TRACK_ASIMAGES
00277 show_progress( "destroying ASImage %p of size %dx%d", *im, (*im)->width, (*im)->height );
00278 remove_hash_item( __as_image_registry, AS_HASHABLE(*im), NULL, False );
00279 #endif
00280 asimage_init( *im, True );
00281 (*im)->magic = 0;
00282 free( *im );
00283 *im = NULL ;
00284 }else if( *im )
00285 {
00286 show_error( "Failed to destroy ASImage %p:", *im );
00287 print_asimage_func (AS_HASHABLE(*im));
00288 }
00289
00290 }
00291 }
00292
00293 void print_asimage_func (ASHashableValue value)
00294 {
00295 ASImage *im = (ASImage*)value ;
00296 if( im && im->magic == MAGIC_ASIMAGE )
00297 {
00298 unsigned int k;
00299 unsigned int red_mem = 0, green_mem = 0, blue_mem = 0, alpha_mem = 0;
00300 unsigned int red_count = 0, green_count = 0, blue_count = 0, alpha_count = 0;
00301 ASStorageSlot slot ;
00302
00303 fprintf( stderr,"\n\tASImage[%p].size = %dx%d;\n", im, im->width, im->height );
00304 fprintf( stderr,"\tASImage[%p].back_color = 0x%lX;\n", im, (long)im->back_color );
00305 fprintf( stderr,"\t\tASImage[%p].alt.ximage = %p;\n", im, im->alt.ximage );
00306 if( im->alt.ximage )
00307 {
00308 fprintf( stderr,"\t\t\tASImage[%p].alt.ximage.bytes_per_line = %d;\n", im, im->alt.ximage->bytes_per_line);
00309 fprintf( stderr,"\t\t\tASImage[%p].alt.ximage.size = %dx%d;\n", im, im->alt.ximage->width, im->alt.ximage->height);
00310 }
00311 fprintf( stderr,"\t\tASImage[%p].alt.mask_ximage = %p;\n", im, im->alt.mask_ximage);
00312 if( im->alt.mask_ximage )
00313 {
00314 fprintf( stderr,"\t\t\tASImage[%p].alt.mask_ximage.bytes_per_line = %d;\n", im, im->alt.mask_ximage->bytes_per_line);
00315 fprintf( stderr,"\t\t\tASImage[%p].alt.mask_ximage.size = %dx%d;\n", im, im->alt.mask_ximage->width, im->alt.mask_ximage->height);
00316 }
00317 fprintf( stderr,"\t\tASImage[%p].alt.argb32 = %p;\n", im, im->alt.argb32 );
00318 fprintf( stderr,"\t\tASImage[%p].alt.vector = %p;\n", im, im->alt.vector );
00319 fprintf( stderr,"\tASImage[%p].imageman = %p;\n", im, im->imageman );
00320 fprintf( stderr,"\tASImage[%p].ref_count = %d;\n", im, im->ref_count );
00321 fprintf( stderr,"\tASImage[%p].name = \"%s\";\n", im, im->name );
00322 fprintf( stderr,"\tASImage[%p].flags = 0x%lX;\n", im, im->flags );
00323
00324 for( k = 0 ; k < im->height ; k++ )
00325 {
00326 if( im->red[k] )
00327 if( query_storage_slot(NULL, im->red[k], &slot ) )
00328 {
00329 ++red_count;
00330 red_mem += slot.size ;
00331 }
00332 if( im->green[k] )
00333 if( query_storage_slot(NULL, im->green[k], &slot ) )
00334 {
00335 ++green_count;
00336 green_mem += slot.size ;
00337 }
00338 if( im->blue[k] )
00339 if( query_storage_slot(NULL, im->blue[k], &slot ) )
00340 {
00341 ++blue_count;
00342 blue_mem += slot.size ;
00343 }
00344 if( im->alpha[k] )
00345 if( query_storage_slot(NULL, im->alpha[k], &slot ) )
00346 {
00347 ++alpha_count;
00348 alpha_mem += slot.size ;
00349 }
00350 }
00351
00352 fprintf( stderr,"\tASImage[%p].uncompressed_size = %d;\n", im, im->width*red_count +
00353 im->width*green_count +
00354 im->width*blue_count +
00355 im->width*alpha_count );
00356 fprintf( stderr,"\tASImage[%p].compressed_size = %d;\n", im, red_mem + green_mem +blue_mem + alpha_mem );
00357 fprintf( stderr,"\t\tASImage[%p].channel[red].lines_count = %d;\n", im, red_count );
00358 fprintf( stderr,"\t\tASImage[%p].channel[red].memory_used = %d;\n", im, red_mem );
00359 fprintf( stderr,"\t\tASImage[%p].channel[green].lines_count = %d;\n", im, green_count );
00360 fprintf( stderr,"\t\tASImage[%p].channel[green].memory_used = %d;\n", im, green_mem );
00361 fprintf( stderr,"\t\tASImage[%p].channel[blue].lines_count = %d;\n", im, blue_count );
00362 fprintf( stderr,"\t\tASImage[%p].channel[blue].memory_used = %d;\n", im, blue_mem );
00363 fprintf( stderr,"\t\tASImage[%p].channel[alpha].lines_count = %d;\n", im, alpha_count );
00364 fprintf( stderr,"\t\tASImage[%p].channel[alpha].memory_used = %d;\n", im, alpha_mem );
00365 }
00366 }
00367
00368 void
00369 print_asimage_registry()
00370 {
00371 #ifdef TRACK_ASIMAGES
00372 print_ashash( __as_image_registry, print_asimage_func );
00373 #endif
00374 }
00375
00376 void
00377 purge_asimage_registry()
00378 {
00379 #ifdef TRACK_ASIMAGES
00380 if( __as_image_registry )
00381 destroy_ashash( &__as_image_registry );
00382 #endif
00383 }
00384
00385
00386 static void
00387 asimage_destroy (ASHashableValue value, void *data)
00388 {
00389 if( data )
00390 {
00391 ASImage *im = (ASImage*)data ;
00392 if( im != NULL )
00393 {
00394 if( AS_ASSERT_NOTVAL(im->magic, MAGIC_ASIMAGE) )
00395 im = NULL ;
00396 else
00397 im->imageman = NULL ;
00398 }
00399 if( im == NULL || (char*)value != im->name )
00400 free( (char*)value );
00401 destroy_asimage( &im );
00402 }
00403 }
00404
00405 ASImageManager *create_image_manager( struct ASImageManager *reusable_memory, double gamma, ... )
00406 {
00407 ASImageManager *imman = reusable_memory ;
00408 int i ;
00409 va_list ap;
00410
00411 if( imman == NULL )
00412 imman = safecalloc( 1, sizeof(ASImageManager));
00413 else
00414 memset( imman, 0x00, sizeof(ASImageManager));
00415
00416 va_start (ap, gamma);
00417 for( i = 0 ; i < MAX_SEARCH_PATHS ; i++ )
00418 {
00419 char *path = va_arg(ap,char*);
00420 if( path == NULL )
00421 break;
00422 imman->search_path[i] = mystrdup( path );
00423 }
00424 va_end (ap);
00425
00426 imman->search_path[MAX_SEARCH_PATHS] = NULL ;
00427 imman->gamma = gamma ;
00428
00429 imman->image_hash = create_ashash( 7, string_hash_value, string_compare, asimage_destroy );
00430
00431 return imman;
00432 }
00433
00434 void
00435 destroy_image_manager( struct ASImageManager *imman, Bool reusable )
00436 {
00437 if( imman )
00438 {
00439 int i = MAX_SEARCH_PATHS;
00440 destroy_ashash( &(imman->image_hash) );
00441 while( --i >= 0 )
00442 if(imman->search_path[i])
00443 free( imman->search_path[i] );
00444
00445 if( !reusable )
00446 free( imman );
00447 else
00448 memset( imman, 0x00, sizeof(ASImageManager));
00449 }
00450 }
00451
00452 Bool
00453 store_asimage( ASImageManager* imageman, ASImage *im, const char *name )
00454 {
00455 Bool res = False ;
00456 if( !AS_ASSERT(im) )
00457 if( AS_ASSERT_NOTVAL(im->magic, MAGIC_ASIMAGE) )
00458 im = NULL ;
00459 if( !AS_ASSERT(imageman) && !AS_ASSERT(im) && !AS_ASSERT((char*)name) )
00460 {
00461 if( im->imageman == NULL )
00462 {
00463 int hash_res ;
00464 char *stored_name = mystrdup( name );
00465 if( im->name )
00466 free( im->name );
00467 im->name = stored_name ;
00468 hash_res = add_hash_item( imageman->image_hash, AS_HASHABLE(im->name), im);
00469 res = ( hash_res == ASH_Success);
00470 if( !res )
00471 {
00472 free( im->name );
00473 im->name = NULL ;
00474 }else
00475 {
00476 im->imageman = imageman ;
00477 im->ref_count = 1 ;
00478 }
00479 }
00480 }
00481 return res ;
00482 }
00483
00484 inline ASImage *
00485 query_asimage( ASImageManager* imageman, const char *name )
00486 {
00487 ASImage *im = NULL ;
00488 if( !AS_ASSERT(imageman) && !AS_ASSERT(name) )
00489 {
00490 ASHashData hdata = {0} ;
00491 if( get_hash_item( imageman->image_hash, AS_HASHABLE((char*)name), &hdata.vptr) == ASH_Success )
00492 {
00493 im = hdata.vptr ;
00494 if( im->magic != MAGIC_ASIMAGE )
00495 im = NULL ;
00496 }
00497 }
00498 return im;
00499 }
00500
00501 ASImage *
00502 fetch_asimage( ASImageManager* imageman, const char *name )
00503 {
00504 ASImage *im = query_asimage( imageman, name );
00505 if( im )
00506 {
00507 im->ref_count++ ;
00508 }
00509 return im;
00510 }
00511
00512
00513 ASImage *
00514 dup_asimage( ASImage* im )
00515 {
00516 if( !AS_ASSERT(im) )
00517 if( AS_ASSERT_NOTVAL(im->magic,MAGIC_ASIMAGE) )
00518 {
00519 im = NULL ;
00520 show_error( "ASImage %p has invalid magic number - discarding!", im );
00521 }
00522
00523 if( !AS_ASSERT(im) && !AS_ASSERT(im->imageman) )
00524 {
00525
00526 im->ref_count++ ;
00527 return im;
00528 }else if( im )
00529 {
00530 show_debug( __FILE__, "dup_asimage", __LINE__, "Attempt to duplicate ASImage %p that is not tracked by any image manager!", im );
00531 }
00532 return NULL ;
00533 }
00534
00535 inline int
00536 release_asimage( ASImage *im )
00537 {
00538 int res = -1 ;
00539 if( !AS_ASSERT(im) )
00540 {
00541 if( im->magic == MAGIC_ASIMAGE )
00542 {
00543 if( --(im->ref_count) <= 0 )
00544 {
00545 ASImageManager *imman = im->imageman ;
00546 if( !AS_ASSERT(imman) )
00547 if( remove_hash_item(imman->image_hash, (ASHashableValue)(char*)im->name, NULL, True) != ASH_Success )
00548 destroy_asimage( &im );
00549 }else
00550 res = im->ref_count ;
00551 }
00552 }
00553 return res ;
00554 }
00555
00556 void
00557 forget_asimage( ASImage *im )
00558 {
00559 if( !AS_ASSERT(im) )
00560 {
00561 if( im->magic == MAGIC_ASIMAGE )
00562 {
00563 ASImageManager *imman = im->imageman ;
00564 if( !AS_ASSERT(imman) )
00565 remove_hash_item(imman->image_hash, (ASHashableValue)(char*)im->name, NULL, False);
00566 im->ref_count = 0;
00567 im->imageman = NULL;
00568 }
00569 }
00570 }
00571
00572 void
00573 relocate_asimage( ASImageManager* to_imageman, ASImage *im )
00574 {
00575 if( !AS_ASSERT(im) )
00576 {
00577 if( im->magic == MAGIC_ASIMAGE )
00578 {
00579 ASImageManager *imman = im->imageman ;
00580 int ref_count = im->ref_count ;
00581 if( imman != NULL )
00582 {
00583 remove_hash_item(imman->image_hash, (ASHashableValue)(char*)im->name, NULL, False);
00584 im->ref_count = 0;
00585 im->imageman = NULL;
00586 }
00587 if( to_imageman != NULL )
00588 {
00589 if( add_hash_item( to_imageman->image_hash, AS_HASHABLE(im->name), im) == ASH_Success )
00590 {
00591 im->ref_count = ref_count < 1 ? 1: ref_count;
00592 im->imageman = to_imageman ;
00593 }
00594 }
00595 }
00596 }
00597 }
00598
00599 void
00600 forget_asimage_name( ASImageManager *imman, const char *name )
00601 {
00602 if( !AS_ASSERT(imman) && name != NULL )
00603 {
00604 remove_hash_item(imman->image_hash, AS_HASHABLE((char*)name), NULL, False);
00605 }
00606 }
00607
00608 inline int
00609 safe_asimage_destroy( ASImage *im )
00610 {
00611 int res = -1 ;
00612 if( !AS_ASSERT(im) )
00613 {
00614 if( im->magic == MAGIC_ASIMAGE )
00615 {
00616 ASImageManager *imman = im->imageman ;
00617 if( imman != NULL )
00618 {
00619 res = --(im->ref_count) ;
00620 if( im->ref_count <= 0 )
00621 remove_hash_item(imman->image_hash, (ASHashableValue)(char*)im->name, NULL, True);
00622 }else
00623 {
00624 destroy_asimage( &im );
00625 res = -1 ;
00626 }
00627 }
00628 }
00629 return res ;
00630 }
00631
00632 int
00633 release_asimage_by_name( ASImageManager *imageman, char *name )
00634 {
00635 int res = -1 ;
00636 ASImage *im = NULL ;
00637 if( !AS_ASSERT(imageman) && !AS_ASSERT(name) )
00638 {
00639 ASHashData hdata ;
00640 if( get_hash_item( imageman->image_hash, AS_HASHABLE((char*)name), &hdata.vptr) == ASH_Success )
00641 {
00642 im = hdata.vptr ;
00643 res = release_asimage( im );
00644 }
00645 }
00646 return res ;
00647 }
00648
00649 void
00650 print_asimage_manager(ASImageManager *imageman)
00651 {
00652 #ifdef TRACK_ASIMAGES
00653 print_ashash( imageman->image_hash, string_print );
00654 #endif
00655 }
00656
00657
00658
00659 void
00660 destroy_asgradient( ASGradient **pgrad )
00661 {
00662 if( pgrad && *pgrad )
00663 {
00664 if( (*pgrad)->color )
00665 {
00666 free( (*pgrad)->color );
00667 (*pgrad)->color = NULL ;
00668 }
00669 if( (*pgrad)->offset )
00670 {
00671 free( (*pgrad)->offset );
00672 (*pgrad)->offset = NULL ;
00673 }
00674 (*pgrad)->npoints = 0 ;
00675 free( *pgrad );
00676 *pgrad = NULL ;
00677 }
00678
00679 }
00680
00681 ASGradient *
00682 flip_gradient( ASGradient *orig, int flip )
00683 {
00684 ASGradient *grad ;
00685 int npoints ;
00686 int type ;
00687 Bool inverse_points = False ;
00688
00689 flip &= FLIP_MASK ;
00690 if( orig == NULL || flip == 0 )
00691 return orig;
00692
00693 grad = safecalloc( 1, sizeof(ASGradient));
00694
00695 grad->npoints = npoints = orig->npoints ;
00696 type = orig->type ;
00697 grad->color = safemalloc( npoints*sizeof(ARGB32) );
00698 grad->offset = safemalloc( npoints*sizeof(double) );
00699
00700 if( get_flags(flip, FLIP_VERTICAL) )
00701 {
00702 Bool upsidedown = get_flags(flip, FLIP_UPSIDEDOWN) ;
00703 switch(type)
00704 {
00705 case GRADIENT_Left2Right :
00706 type = GRADIENT_Top2Bottom ; inverse_points = !upsidedown ;
00707 break;
00708 case GRADIENT_TopLeft2BottomRight :
00709 type = GRADIENT_BottomLeft2TopRight ; inverse_points = upsidedown ;
00710 break;
00711 case GRADIENT_Top2Bottom :
00712 type = GRADIENT_Left2Right ; inverse_points = upsidedown ;
00713 break;
00714 case GRADIENT_BottomLeft2TopRight :
00715 type = GRADIENT_TopLeft2BottomRight ; inverse_points = !upsidedown ;
00716 break;
00717 }
00718 }else if( flip == FLIP_UPSIDEDOWN )
00719 {
00720 inverse_points = True ;
00721 }
00722
00723 grad->type = type ;
00724 if( inverse_points )
00725 {
00726 register int i = 0, k = npoints;
00727 while( --k >= 0 )
00728 {
00729 grad->color[i] = orig->color[k] ;
00730 grad->offset[i] = 1.0 - orig->offset[k] ;
00731 ++i ;
00732 }
00733 }else
00734 {
00735 register int i = npoints ;
00736 while( --i >= 0 )
00737 {
00738 grad->color[i] = orig->color[i] ;
00739 grad->offset[i] = orig->offset[i] ;
00740 }
00741 }
00742 return grad;
00743 }
00744
00745
00746
00747 void
00748 init_image_layers( register ASImageLayer *l, int count )
00749 {
00750 memset( l, 0x00, sizeof(ASImageLayer)*count );
00751 while( --count >= 0 )
00752 {
00753 l[count].merge_scanlines = alphablend_scanlines ;
00754
00755 }
00756 }
00757
00758 ASImageLayer *
00759 create_image_layers( int count )
00760 {
00761 ASImageLayer *l = NULL;
00762
00763 if( count > 0 )
00764 {
00765 l = safecalloc( count, sizeof(ASImageLayer) );
00766 init_image_layers( l, count );
00767 }
00768 return l;
00769 }
00770
00771 void
00772 destroy_image_layers( register ASImageLayer *l, int count, Bool reusable )
00773 {
00774 if( l )
00775 {
00776 register int i = count;
00777 while( --i >= 0 )
00778 {
00779 if( l[i].im )
00780 {
00781 if( l[i].im->imageman )
00782 release_asimage( l[i].im );
00783 else
00784 destroy_asimage( &(l[i].im) );
00785 }
00786 if( l[i].bevel )
00787 free( l[i].bevel );
00788 }
00789 if( !reusable )
00790 free( l );
00791 else
00792 memset( l, 0x00, sizeof(ASImageLayer)*count );
00793 }
00794 }
00795
00796
00797
00798
00799
00800
00801 size_t
00802 asimage_add_line_mono (ASImage * im, ColorPart color, CARD8 value, unsigned int y)
00803 {
00804 if (AS_ASSERT(im) || color <0 || color >= IC_NUM_CHANNELS )
00805 return 0;
00806 if (y >= im->height)
00807 return 0;
00808
00809 if( im->channels[color][y] )
00810 forget_data( NULL, im->channels[color][y] );
00811 im->channels[color][y] = store_data( NULL, &value, 1, 0, 0);
00812 return im->width;
00813 }
00814
00815 size_t
00816 asimage_add_line (ASImage * im, ColorPart color, register CARD32 * data, unsigned int y)
00817 {
00818 if (AS_ASSERT(im) || color <0 || color >= IC_NUM_CHANNELS )
00819 return 0;
00820 if (y >= im->height)
00821 return 0;
00822 if( im->channels[color][y] )
00823 forget_data( NULL, im->channels[color][y] );
00824 im->channels[color][y] = store_data( NULL, (CARD8*)data, im->width*4, ASStorage_RLEDiffCompress|ASStorage_32Bit, 0);
00825 return im->width;
00826 }
00827
00828 size_t
00829 asimage_add_line_bgra (ASImage * im, register CARD32 * data, unsigned int y)
00830 {
00831 if (AS_ASSERT(im) )
00832 return 0;
00833 if (y >= im->height)
00834 return 0;
00835 if( im->channels[IC_ALPHA][y] )
00836 forget_data( NULL, im->channels[IC_ALPHA][y] );
00837 im->channels[IC_ALPHA][y] = store_data( NULL, (CARD8*)data, im->width*4,
00838 ASStorage_24BitShift|ASStorage_Masked|
00839 ASStorage_RLEDiffCompress|ASStorage_32Bit, 0);
00840 if( im->channels[IC_RED][y] )
00841 forget_data( NULL, im->channels[IC_RED][y] );
00842 im->channels[IC_RED][y] = store_data( NULL, (CARD8*)data, im->width*4,
00843 ASStorage_16BitShift|ASStorage_Masked|
00844 ASStorage_RLEDiffCompress|ASStorage_32Bit, 0);
00845 if( im->channels[IC_GREEN][y] )
00846 forget_data( NULL, im->channels[IC_GREEN][y] );
00847 im->channels[IC_GREEN][y] = store_data( NULL, (CARD8*)data, im->width*4,
00848 ASStorage_8BitShift|ASStorage_Masked|
00849 ASStorage_RLEDiffCompress|ASStorage_32Bit, 0);
00850 if( im->channels[IC_BLUE][y] )
00851 forget_data( NULL, im->channels[IC_BLUE][y] );
00852 im->channels[IC_BLUE][y] = store_data( NULL, (CARD8*)data, im->width*4,
00853 ASStorage_Masked|
00854 ASStorage_RLEDiffCompress|ASStorage_32Bit, 0);
00855 return im->width;
00856 }
00857
00858 unsigned int
00859 asimage_print_line (ASImage * im, ColorPart color, unsigned int y, unsigned long verbosity)
00860 {
00861 if (AS_ASSERT(im) || color < 0 || color >= IC_NUM_CHANNELS )
00862 return 0;
00863 if (y >= im->height)
00864 return 0;
00865
00866 return print_storage_slot(NULL, im->channels[color][y]);
00867 }
00868
00869 void print_asimage( ASImage *im, int flags, char * func, int line )
00870 {
00871 if( im )
00872 {
00873 register unsigned int k ;
00874 int total_mem = 0 ;
00875 fprintf( stderr, "%s:%d> printing ASImage %p.\n", func, line, im);
00876 for( k = 0 ; k < im->height ; k++ )
00877 {
00878 fprintf( stderr, "%s:%d> ******* %d *******\n", func, line, k );
00879 total_mem+=asimage_print_line( im, IC_RED , k, flags );
00880 total_mem+=asimage_print_line( im, IC_GREEN, k, flags );
00881 total_mem+=asimage_print_line( im, IC_BLUE , k, flags );
00882 total_mem+=asimage_print_line( im, IC_ALPHA , k, flags );
00883 }
00884 fprintf( stderr, "%s:%d> Total memory : %u - image size %dx%d ratio %d%%\n", func, line, total_mem, im->width, im->height, (total_mem*100)/(im->width*im->height*3) );
00885 }else
00886 fprintf( stderr, "%s:%d> Attempted to print NULL ASImage.\n", func, line);
00887 }
00888
00889 void print_component( register CARD32 *data, int nonsense, int len );
00890
00891 int
00892 asimage_decode_line (ASImage * im, ColorPart color, CARD32 * to_buf, unsigned int y, unsigned int skip, unsigned int out_width)
00893 {
00894 ASStorageID id = im->channels[color][y];
00895 register int i = 0;
00896
00897 LOCAL_DEBUG_CALLER_OUT( "im->width = %d, color = %d, y = %d, skip = %d, out_width = %d", im->width, color, y, skip, out_width );
00898
00899 if( id )
00900 {
00901 i = fetch_data32( NULL, id, to_buf, skip, out_width, 0, NULL);
00902 LOCAL_DEBUG_OUT( "decoded %d pixels", i );
00903 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
00904 {
00905 int z = -1 ;
00906 while( ++z < i )
00907 fprintf( stderr, "%lX ", (unsigned long)to_buf[z] );
00908 fprintf( stderr, "\n");
00909
00910 }
00911 #endif
00912 return i;
00913 }
00914 return 0;
00915 }
00916
00917 void
00918 move_asimage_channel( ASImage *dst, int channel_dst, ASImage *src, int channel_src )
00919 {
00920 if( !AS_ASSERT(dst) && !AS_ASSERT(src) && channel_src >= 0 && channel_src < IC_NUM_CHANNELS &&
00921 channel_dst >= 0 && channel_dst < IC_NUM_CHANNELS )
00922 {
00923 register int i = MIN(dst->height, src->height);
00924 register ASStorageID *dst_rows = dst->channels[channel_dst] ;
00925 register ASStorageID *src_rows = src->channels[channel_src] ;
00926 while( --i >= 0 )
00927 {
00928 if( dst_rows[i] )
00929 forget_data( NULL, dst_rows[i] );
00930 dst_rows[i] = src_rows[i] ;
00931 src_rows[i] = 0 ;
00932 }
00933 }
00934 }
00935
00936
00937 void
00938 copy_asimage_channel( ASImage *dst, int channel_dst, ASImage *src, int channel_src )
00939 {
00940 if( !AS_ASSERT(dst) && !AS_ASSERT(src) && channel_src >= 0 && channel_src < IC_NUM_CHANNELS &&
00941 channel_dst >= 0 && channel_dst < IC_NUM_CHANNELS )
00942 {
00943 register int i = MIN(dst->height, src->height);
00944 register ASStorageID *dst_rows = dst->channels[channel_dst] ;
00945 register ASStorageID *src_rows = src->channels[channel_src] ;
00946 LOCAL_DEBUG_OUT( "src = %p, dst = %p, dst->width = %d, src->width = %d", src, dst, dst->width, src->width );
00947 while( --i >= 0 )
00948 {
00949 if( dst_rows[i] )
00950 forget_data( NULL, dst_rows[i] );
00951 dst_rows[i] = dup_data( NULL, src_rows[i] );
00952 }
00953 }
00954 }
00955
00956 void
00957 copy_asimage_lines( ASImage *dst, unsigned int offset_dst,
00958 ASImage *src, unsigned int offset_src,
00959 unsigned int nlines, ASFlagType filter )
00960 {
00961 if( !AS_ASSERT(dst) && !AS_ASSERT(src) &&
00962 offset_src < src->height && offset_dst < dst->height )
00963 {
00964 int chan;
00965
00966 if( offset_src+nlines > src->height )
00967 nlines = src->height - offset_src ;
00968 if( offset_dst+nlines > dst->height )
00969 nlines = dst->height - offset_dst ;
00970
00971 for( chan = 0 ; chan < IC_NUM_CHANNELS ; ++chan )
00972 if( get_flags( filter, 0x01<<chan ) )
00973 {
00974 register int i = -1;
00975 register ASStorageID *dst_rows = &(dst->channels[chan][offset_dst]) ;
00976 register ASStorageID *src_rows = &(src->channels[chan][offset_src]) ;
00977 LOCAL_DEBUG_OUT( "copying %d lines of channel %d...", nlines, chan );
00978 while( ++i < (int)nlines )
00979 {
00980 if( dst_rows[i] )
00981 forget_data( NULL, dst_rows[i] );
00982 dst_rows[i] = dup_data( NULL, src_rows[i] );
00983 }
00984 }
00985 #if 0
00986 for( i = 0 ; i < nlines ; ++i )
00987 {
00988 asimage_print_line( src, IC_ALPHA, i, (i==4)?VRB_EVERYTHING:VRB_LINE_SUMMARY );
00989 asimage_print_line( dst, IC_ALPHA, i, (i==4)?VRB_EVERYTHING:VRB_LINE_SUMMARY );
00990 }
00991 #endif
00992 }
00993 }
00994
00995 Bool
00996 asimage_compare_line (ASImage *im, ColorPart color, CARD32 *to_buf, CARD32 *tmp, unsigned int y, Bool verbose)
00997 {
00998 register unsigned int i;
00999 asimage_decode_line( im, color, tmp, y, 0, im->width );
01000 for( i = 0 ; i < im->width ; i++ )
01001 if( tmp[i] != to_buf[i] )
01002 {
01003 if( verbose )
01004 show_error( "line %d, component %d differ at offset %d ( 0x%lX(compresed) != 0x%lX(orig) )\n", y, color, i, (unsigned long)tmp[i], (unsigned long)to_buf[i] );
01005 return False ;
01006 }
01007 return True;
01008 }
01009
01010 ASFlagType
01011 get_asimage_chanmask( ASImage *im)
01012 {
01013 ASFlagType mask = 0 ;
01014 int color ;
01015
01016 if( !AS_ASSERT(im) )
01017 for( color = 0; color < IC_NUM_CHANNELS ; color++ )
01018 {
01019 register ASStorageID *chan = im->channels[color];
01020 register int y, height = im->height ;
01021 for( y = 0 ; y < height ; y++ )
01022 if( chan[y] )
01023 {
01024 set_flags( mask, 0x01<<color );
01025 break;
01026 }
01027 }
01028 return mask ;
01029 }
01030
01031 int
01032 check_asimage_alpha (ASVisual *asv, ASImage *im )
01033 {
01034 int recomended_depth = 0 ;
01035 unsigned int i;
01036 ASScanline buf;
01037
01038 if( asv == NULL )
01039 asv = get_default_asvisual();
01040
01041 if (im == NULL)
01042 return 0;
01043
01044 prepare_scanline( im->width, 0, &buf, asv->BGR_mode );
01045 buf.flags = SCL_DO_ALPHA ;
01046 for (i = 0; i < im->height; i++)
01047 {
01048 int count = asimage_decode_line (im, IC_ALPHA, buf.alpha, i, 0, buf.width);
01049 if( count < (int)buf.width )
01050 {
01051 if( ARGB32_ALPHA8(im->back_color) == 0 )
01052 {
01053 if( recomended_depth == 0 )
01054 recomended_depth = 1 ;
01055 }else if( ARGB32_ALPHA8(im->back_color) != 0xFF )
01056 {
01057 recomended_depth = 8 ;
01058 break ;
01059 }
01060 }
01061 while( --count >= 0 )
01062 if( buf.alpha[count] == 0 )
01063 {
01064 if( recomended_depth == 0 )
01065 recomended_depth = 1 ;
01066 }else if( (buf.alpha[count]&0xFF) != 0xFF )
01067 {
01068 recomended_depth = 8 ;
01069 break ;
01070 }
01071 if( recomended_depth == 8 )
01072 break;
01073 }
01074 free_scanline(&buf, True);
01075
01076 return recomended_depth;
01077 }
01078
01079
01080
01081
01082
01083
01084 Bool
01085 set_asimage_vector( ASImage *im, register double *vector )
01086 {
01087 if( vector == NULL || im == NULL )
01088 return False;
01089
01090 if( im->alt.vector == NULL )
01091 im->alt.vector = safemalloc( im->width*im->height*sizeof(double));
01092
01093 {
01094 register double *dst = im->alt.vector ;
01095 register int i = im->width*im->height;
01096 while( --i >= 0 )
01097 dst[i] = vector[i] ;
01098 }
01099
01100 return True;
01101 }
01102
01103 ASVectorPalette*
01104 vectorize_asimage( ASImage *im, unsigned int max_colors, unsigned int dither,
01105 int opaque_threshold )
01106 {
01107 ASVectorPalette* pal ;
01108 double *vec ;
01109 ASColormap cmap;
01110 unsigned int r, g, b, v;
01111 unsigned int x, y, j ;
01112
01113 if( im->alt.vector == NULL )
01114 im->alt.vector = safemalloc( im->width*im->height*sizeof(double));
01115 vec = im->alt.vector ;
01116
01117
01118
01119 dither = dither > 7 ? 7 : dither;
01120 {
01121 int *res = colormap_asimage(im, &cmap, max_colors, dither, opaque_threshold);
01122
01123 for ( y = 0; y < im->height; y++)
01124 {
01125 for ( x = 0; x < im->width; x++)
01126 {
01127 int i = y*im->width + x;
01128 g = INDEX_SHIFT_GREEN(cmap.entries[res[i]].green);
01129 b = INDEX_SHIFT_BLUE(cmap.entries[res[i]].blue);
01130 r = INDEX_SHIFT_RED(cmap.entries[res[i]].red);
01131 v = MAKE_INDEXED_COLOR24(r,g,b);
01132 v = (v>>12)&0x0FFF;
01133 vec[(im->height - y - 1)*im->width + x] = ((double)v)/0x0FFF;
01134 }
01135 }
01136
01137 free (res);
01138 }
01139 pal = safecalloc( 1, sizeof(ASVectorPalette));
01140
01141 pal->npoints = cmap.count ;
01142 pal->points = safemalloc( sizeof(double)*cmap.count);
01143 pal->channels[IC_RED] = safemalloc( sizeof(CARD16)*cmap.count);
01144 pal->channels[IC_GREEN] = safemalloc( sizeof(CARD16)*cmap.count);
01145 pal->channels[IC_BLUE] = safemalloc( sizeof(CARD16)*cmap.count);
01146 pal->channels[IC_ALPHA] = safemalloc( sizeof(CARD16)*cmap.count);
01147
01148 for ( j = 0; j < cmap.count; j++) {
01149 g = INDEX_SHIFT_GREEN(cmap.entries[j].green);
01150 b = INDEX_SHIFT_BLUE(cmap.entries[j].blue);
01151 r = INDEX_SHIFT_RED(cmap.entries[j].red);
01152 v = MAKE_INDEXED_COLOR24(r,g,b);
01153
01154 v = (v>>12)&0x0FFF;
01155 pal->points[j] = ((double)v)/0x0FFF;
01156
01157 pal->channels[IC_RED][j] = cmap.entries[j].red<<QUANT_ERR_BITS;
01158 pal->channels[IC_GREEN][j] = cmap.entries[j].green<<QUANT_ERR_BITS;
01159 pal->channels[IC_BLUE][j] = cmap.entries[j].blue<<QUANT_ERR_BITS;
01160 pal->channels[IC_ALPHA][j] = 0xFFFF;
01161 }
01162
01163 destroy_colormap(&cmap, True);
01164
01165 return pal;
01166 }
01167
01168
01169
01170
01171 ASImage*
01172 clone_asimage( ASImage *src, ASFlagType filter )
01173 {
01174 ASImage *dst = NULL ;
01175 START_TIME(started);
01176
01177 if( !AS_ASSERT(src) )
01178 {
01179 int chan ;
01180 dst = create_asimage(src->width, src->height, 100);
01181 if( get_flags( src->flags, ASIM_DATA_NOT_USEFUL ) )
01182 set_flags( dst->flags, ASIM_DATA_NOT_USEFUL );
01183 dst->back_color = src->back_color ;
01184 for( chan = 0 ; chan < IC_NUM_CHANNELS; chan++ )
01185 if( get_flags( filter, 0x01<<chan) )
01186 {
01187 register int i = dst->height;
01188 register ASStorageID *dst_rows = dst->channels[chan] ;
01189 register ASStorageID *src_rows = src->channels[chan] ;
01190 while( --i >= 0 )
01191 dst_rows[i] = dup_data( NULL, src_rows[i] );
01192 }
01193 }
01194 SHOW_TIME("", started);
01195 return dst;
01196 }
01197
01198
01199
01200
01201
01202 XRectangle*
01203 get_asimage_channel_rects( ASImage *src, int channel, unsigned int threshold, unsigned int *rects_count_ret )
01204 {
01205 XRectangle *rects = NULL ;
01206 int rects_count = 0, rects_allocated = 0 ;
01207
01208 START_TIME(started);
01209
01210 if( !AS_ASSERT(src) && channel < IC_NUM_CHANNELS )
01211 {
01212 int i = src->height;
01213 ASStorageID *src_rows = src->channels[channel] ;
01214 unsigned int *height = safemalloc( (src->width+1)*2 * sizeof(unsigned int) );
01215 unsigned int *prev_runs = NULL ;
01216 int prev_runs_count = 0 ;
01217 unsigned int *runs = safemalloc( (src->width+1)*2 * sizeof(unsigned int) );
01218 unsigned int *tmp_runs = safemalloc( (src->width+1)*2 * sizeof(unsigned int) );
01219 unsigned int *tmp_height = safemalloc( (src->width+1)*2 * sizeof(unsigned int) );
01220 Bool count_empty = (ARGB32_CHAN8(src->back_color,channel)>= threshold);
01221
01222 #ifdef DEBUG_RECTS
01223 fprintf( stderr, "%d:back_color = #%8.8lX, count_empty = %d, thershold = %d\n", __LINE__, src->back_color, count_empty, threshold );
01224 #endif
01225 while( --i >= -1 )
01226 {
01227 int runs_count = 0 ;
01228 #ifdef DEBUG_RECTS
01229 fprintf( stderr, "%d: LINE %d **********************\n", __LINE__, i );
01230 #ifdef DEBUG_RECTS2
01231 asimage_print_line (src, channel, i, 0xFFFFFFFF);
01232 #else
01233 asimage_print_line (src, channel, i, VRB_LINE_CONTENT);
01234 #endif
01235 #endif
01236 if( i >= 0 )
01237 {
01238 if( src_rows[i] )
01239 {
01240 runs_count = threshold_stored_data(NULL, src_rows[i], runs, src->width, threshold);
01241 }else if( count_empty )
01242 {
01243 runs_count = 2 ;
01244 runs[0] = 0 ;
01245 runs[1] = src->width ;
01246 }
01247 }
01248 #ifdef DEBUG_RECTS
01249 fprintf( stderr, "runs_count = %d\n", runs_count );
01250 #endif
01251 if( runs_count > 0 && (runs_count &0x0001) != 0 )
01252 {
01253 runs[runs_count] = 0 ;
01254 ++runs_count ;
01255 }
01256
01257 if( prev_runs_count > 0 )
01258 {
01259 int k = 0, l = 0, last_k = 0 ;
01260 int tmp_count = 0 ;
01261 unsigned int *tmp ;
01262 if( runs_count == 0 )
01263 {
01264 runs[0] = src->width ;
01265 runs[1] = src->width ;
01266 runs_count = 2 ;
01267 }
01268 tmp_runs[0] = 0 ;
01269 tmp_runs[1] = src->width ;
01270
01271
01272
01273 for( l = 0 ; l < prev_runs_count ; ++l, ++l )
01274 {
01275 int start = prev_runs[l], end = prev_runs[l+1] ;
01276 int matching_runs = 0 ;
01277 #ifdef DEBUG_RECTS
01278 fprintf( stderr, "%d: prev run %d : start = %d, end = %d, last_k = %d, height = %d\n", __LINE__, l, start, end, last_k, height[l] );
01279 #endif
01280 for( k = last_k ; k < runs_count ; ++k, ++k )
01281 {
01282 #ifdef DEBUG_RECTS
01283 fprintf( stderr, "*%d: new run %d : start = %d, end = %d\n", __LINE__, k, runs[k], runs[k+1] );
01284 #endif
01285 if( (int)runs[k] > end )
01286 {
01287 if( rects_count >= rects_allocated )
01288 {
01289 rects_allocated = rects_count + 8 + (rects_count>>3);
01290 rects = realloc( rects, rects_allocated*sizeof(XRectangle));
01291 }
01292 rects[rects_count].x = start ;
01293 rects[rects_count].y = i+1 ;
01294 rects[rects_count].width = (end-start)+1 ;
01295 rects[rects_count].height = height[l] ;
01296 #ifdef DEBUG_RECTS
01297 fprintf( stderr, "*%d: added rectangle at y = %d\n", __LINE__, rects[rects_count].y );
01298 #endif
01299 ++rects_count ;
01300 ++matching_runs;
01301 break;
01302 }else if( (int)runs[k+1] >= start )
01303 {
01304 if( start < (int)runs[k] )
01305 {
01306 if( rects_count >= rects_allocated )
01307 {
01308 rects_allocated = rects_count + 8 + (rects_count>>3);
01309 rects = realloc( rects, rects_allocated*sizeof(XRectangle));
01310 }
01311 rects[rects_count].x = start ;
01312 rects[rects_count].y = i+1 ;
01313 rects[rects_count].width = runs[k]-start ;
01314 rects[rects_count].height = height[l] ;
01315 #ifdef DEBUG_RECTS
01316 fprintf( stderr, "*%d: added rectangle at y = %d\n", __LINE__, rects[rects_count].y );
01317 #endif
01318 ++rects_count ;
01319 start = runs[k] ;
01320 }else if( start > (int)runs[k] )
01321 {
01322 tmp_runs[tmp_count] = runs[k] ;
01323 tmp_runs[tmp_count+1] = start-1 ;
01324 tmp_height[tmp_count] = 1 ;
01325 #ifdef DEBUG_RECTS
01326 fprintf( stderr, "*%d: tmp_run %d added : %d ... %d, height = %d\n", __LINE__, tmp_count, runs[k], start-1, 1 );
01327 #endif
01328 ++tmp_count ; ++tmp_count ;
01329 runs[k] = start ;
01330 }
01331
01332 if( end < (int)runs[k+1] )
01333 {
01334 runs[k] = end+1 ;
01335 }else
01336 {
01337 if( end > (int)runs[k+1] )
01338 {
01339
01340 if( rects_count >= rects_allocated )
01341 {
01342 rects_allocated = rects_count + 8 + (rects_count>>3);
01343 rects = realloc( rects, rects_allocated*sizeof(XRectangle));
01344 }
01345 rects[rects_count].x = runs[k+1]+1 ;
01346 rects[rects_count].y = i+1 ;
01347 rects[rects_count].width = end - runs[k+1] ;
01348 rects[rects_count].height = height[l] ;
01349 #ifdef DEBUG_RECTS
01350 fprintf( stderr, "*%d: added rectangle at y = %d\n", __LINE__, rects[rects_count].y );
01351 #endif
01352 ++rects_count ;
01353 end = runs[k+1] ;
01354
01355 }
01356
01357 runs[k] = src->width ;
01358 runs[k+1] = src->width ;
01359 #ifdef DEBUG_RECTS
01360 fprintf( stderr, "*%d: eliminating new run %d\n", __LINE__, k );
01361 #endif
01362 ++k ; ++k ;
01363 }
01364 tmp_runs[tmp_count] = start ;
01365 tmp_runs[tmp_count+1] = end ;
01366 tmp_height[tmp_count] = height[l]+1 ;
01367 #ifdef DEBUG_RECTS
01368 fprintf( stderr, "*%d: tmp_run %d added : %d ... %d, height = %d\n", __LINE__, tmp_count, start, end, height[l]+1 );
01369 #endif
01370 ++tmp_count ; ++tmp_count ;
01371 last_k = k ;
01372 ++matching_runs;
01373 break;
01374 }
01375 }
01376 if( matching_runs == 0 )
01377 {
01378 #ifdef DEBUG_RECTS
01379 fprintf( stderr, "%d: NO MATCHING NEW RUNS : start = %d, end = %d, height = %d\n", __LINE__, start, end, height[l] );
01380 #endif
01381 if( rects_count >= rects_allocated )
01382 {
01383 rects_allocated = rects_count + 8 + (rects_count>>3);
01384 rects = realloc( rects, rects_allocated*sizeof(XRectangle));
01385 }
01386 rects[rects_count].x = start ;
01387 rects[rects_count].y = i+1 ;
01388 rects[rects_count].width = (end-start)+1 ;
01389 rects[rects_count].height = height[l] ;
01390 #ifdef DEBUG_RECTS
01391 fprintf( stderr, "*%d: added rectangle at y = %d\n", __LINE__, rects[rects_count].y );
01392 #endif
01393 ++rects_count ;
01394 }
01395 }
01396
01397
01398 for( k = 0 ; k < runs_count ; ++k, ++k )
01399 if( runs[k] < src->width )
01400 {
01401 int ii = tmp_count ;
01402 while( ii > 0 && tmp_runs[ii-1] > runs[k] )
01403 {
01404 tmp_runs[ii] = tmp_runs[ii-2] ;
01405 tmp_runs[ii+1] = tmp_runs[ii-1] ;
01406 tmp_height[ii] = tmp_height[ii-2] ;
01407 --ii ; --ii ;
01408 }
01409 tmp_runs[ii] = runs[k] ;
01410 tmp_runs[ii+1] = runs[k+1] ;
01411 tmp_height[ii] = 1 ;
01412 #ifdef DEBUG_RECTS
01413 fprintf( stderr, "*%d: tmp_run %d added : %d ... %d, height = %d\n", __LINE__, ii, runs[k], runs[k+1], 1 );
01414 #endif
01415 ++tmp_count, ++tmp_count;
01416 }
01417 tmp = prev_runs ;
01418 prev_runs = tmp_runs ;
01419 tmp_runs = tmp ;
01420 tmp = height ;
01421 height = tmp_height ;
01422 tmp_height = tmp ;
01423 prev_runs_count = tmp_count ;
01424 }else if( runs_count > 0 )
01425 {
01426 int k = runs_count;
01427 prev_runs_count = runs_count ;
01428 prev_runs = runs ;
01429 runs = safemalloc( (src->width+1)*2 * sizeof(unsigned int) );
01430 while( --k >= 0 )
01431 height[k] = 1 ;
01432 }
01433 }
01434 free( runs );
01435 if( prev_runs )
01436 free( prev_runs );
01437 free( tmp_runs );
01438 free( tmp_height );
01439 free( height );
01440 }
01441 SHOW_TIME("", started);
01442
01443 if( rects_count_ret )
01444 *rects_count_ret = rects_count ;
01445
01446 return rects;
01447 }
01448
01449
01450 void
01451 raw2scanline( register CARD8 *row, ASScanline *buf, CARD8 *gamma_table, unsigned int width, Bool grayscale, Bool do_alpha )
01452 {
01453 register int x = width;
01454
01455 if( grayscale )
01456 row += do_alpha? width<<1 : width ;
01457 else
01458 row += width*(do_alpha?4:3) ;
01459
01460 if( gamma_table )
01461 {
01462 if( !grayscale )
01463 {
01464 while ( --x >= 0 )
01465 {
01466 row -= 3 ;
01467 if( do_alpha )
01468 {
01469 --row;
01470 buf->alpha[x] = row[3];
01471 }
01472 buf->xc1[x] = gamma_table[row[0]];
01473 buf->xc2[x]= gamma_table[row[1]];
01474 buf->xc3[x] = gamma_table[row[2]];
01475 }
01476 }else
01477 while ( --x >= 0 )
01478 {
01479 if( do_alpha )
01480 buf->alpha[x] = *(--row);
01481 buf->red [x] = gamma_table[*(--row)];
01482 }
01483 }else
01484 {
01485 if( !grayscale )
01486 {
01487 while ( --x >= 0 )
01488 {
01489 row -= 3 ;
01490 if( do_alpha )
01491 {
01492 --row;
01493 buf->alpha[x] = row[3];
01494 }
01495 buf->xc1[x] = row[0];
01496 buf->xc2[x]= row[1];
01497 buf->xc3[x] = row[2];
01498 }
01499 }else
01500 while ( --x >= 0 )
01501 {
01502 if( do_alpha )
01503 buf->alpha[x] = *(--row);
01504 buf->red [x] = *(--row);
01505 }
01506 }
01507 }
01508
01509
01510
01511
01512