00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #undef LOCAL_DEBUG
00022 #undef DO_CLOCKING
00023 #ifndef NO_DEBUG_OUTPUT
00024 #undef DEBUG_RECTS
00025 #undef DEBUG_RECTS2
00026 #endif
00027
00028 #ifdef _WIN32
00029 #include "win32/config.h"
00030 #else
00031 #include "config.h"
00032 #endif
00033
00034 #include <string.h>
00035 #ifdef DO_CLOCKING
00036 #if TIME_WITH_SYS_TIME
00037 # include <sys/time.h>
00038 # include <time.h>
00039 #else
00040 # if HAVE_SYS_TIME_H
00041 # include <sys/time.h>
00042 # else
00043 # include <time.h>
00044 # endif
00045 #endif
00046 #endif
00047 #ifdef HAVE_UNISTD_H
00048 #include <unistd.h>
00049 #endif
00050 #ifdef HAVE_STDLIB_H
00051 #include <stdlib.h>
00052 #endif
00053 #ifdef HAVE_STDARG_H
00054 #include <stdarg.h>
00055 #endif
00056
00057 #ifdef HAVE_MMX
00058 #include <mmintrin.h>
00059 #endif
00060
00061 #ifdef _WIN32
00062 # include "win32/afterbase.h"
00063 #else
00064 # include "afterbase.h"
00065 #endif
00066 #include "asvisual.h"
00067 #include "blender.h"
00068 #include "asimage.h"
00069 #include "imencdec.h"
00070
00071 static void decode_asscanline_native( ASImageDecoder *imdec, unsigned int skip, int y );
00072 static void decode_asscanline_ximage( ASImageDecoder *imdec, unsigned int skip, int y );
00073 static void decode_asscanline_argb32( ASImageDecoder *imdec, unsigned int skip, int y );
00074
00075 void decode_image_scanline_normal( ASImageDecoder *imdec );
00076 void decode_image_scanline_beveled( ASImageDecoder *imdec );
00077 void decode_image_scl_bevel_solid( ASImageDecoder *imdec );
00078
00079
00080 Bool create_image_xim( ASVisual *asv, ASImage *im, ASAltImFormats format );
00081 Bool create_image_argb32( ASVisual *asv, ASImage *im, ASAltImFormats format );
00082
00083 void encode_image_scanline_asim( ASImageOutput *imout, ASScanline *to_store );
00084 void encode_image_scanline_xim( ASImageOutput *imout, ASScanline *to_store );
00085 void encode_image_scanline_mask_xim( ASImageOutput *imout, ASScanline *to_store );
00086 void encode_image_scanline_argb32( ASImageOutput *imout, ASScanline *to_store );
00087
00088 static struct ASImageFormatHandlers
00089 {
00090 Bool (*check_create_asim_format)( ASVisual *asv, ASImage *im, ASAltImFormats format );
00091 void (*encode_image_scanline)( ASImageOutput *imout, ASScanline *to_store );
00092 }asimage_format_handlers[ASA_Formats] =
00093 {
00094 { NULL, encode_image_scanline_asim },
00095 { create_image_xim, encode_image_scanline_xim },
00096 { create_image_xim, encode_image_scanline_mask_xim },
00097 { create_image_xim, encode_image_scanline_xim },
00098 { create_image_xim, encode_image_scanline_mask_xim },
00099 { create_image_xim, encode_image_scanline_xim },
00100 { create_image_argb32, encode_image_scanline_argb32 },
00101 { NULL, NULL }
00102 };
00103
00104
00105
00106 void output_image_line_top( ASImageOutput *, ASScanline *, int );
00107 void output_image_line_fine( ASImageOutput *, ASScanline *, int );
00108 void output_image_line_fast( ASImageOutput *, ASScanline *, int );
00109 void output_image_line_direct( ASImageOutput *, ASScanline *, int );
00110
00111
00112
00113
00114
00115
00116 static int asimage_quality_level = ASIMAGE_QUALITY_GOOD;
00117
00118
00119 Bool create_image_xim( ASVisual *asv, ASImage *im, ASAltImFormats format )
00120 {
00121 Bool scratch = False, do_alpha = False ;
00122 XImage **dst ;
00123 if( format == ASA_ScratchXImageAndAlpha )
00124 {
00125 format = ASA_ScratchXImage ;
00126 do_alpha = True ;
00127 }
00128
00129 if( format == ASA_ScratchXImage || format == ASA_ScratchMaskXImage )
00130 {
00131 scratch = True ;
00132 format = (format - ASA_ScratchXImage ) + ASA_XImage ;
00133 }
00134 dst = (format == ASA_MaskXImage )? &(im->alt.mask_ximage):&(im->alt.ximage);
00135 if( *dst == NULL )
00136 {
00137 int depth = 0 ;
00138 if( format == ASA_MaskXImage )
00139 depth = get_flags(im->flags, ASIM_XIMAGE_8BIT_MASK )? 8: 1;
00140 if( scratch )
00141 *dst = create_visual_scratch_ximage( asv, im->width, im->height, depth );
00142 else
00143 *dst = create_visual_ximage( asv, im->width, im->height, depth );
00144 if( *dst == NULL )
00145 show_error( "Unable to create %sXImage for the visual %d",
00146 (format == ASA_MaskXImage )?"mask ":"",
00147 asv->visual_info.visualid );
00148 }
00149 return ( *dst != NULL );
00150 }
00151
00152 Bool create_image_argb32( ASVisual *asv, ASImage *im, ASAltImFormats format )
00153 {
00154 if( im->alt.argb32 == NULL )
00155 im->alt.argb32 = safemalloc( im->width*im->height*sizeof(ARGB32) );
00156 return True;
00157 }
00158
00159
00160
00161 static void
00162 asimage_dup_line (ASImage * im, ColorPart color, unsigned int y1, unsigned int y2, unsigned int length)
00163 {
00164 ASStorageID *part = im->channels[color];
00165 if (part[y2] != 0)
00166 {
00167 forget_data(NULL, part[y2]);
00168 part[y2] = 0 ;
00169 }
00170 if( part[y1] )
00171 part[y2] = dup_data(NULL, part[y1] );
00172 }
00173
00174 void
00175 asimage_erase_line( ASImage * im, ColorPart color, unsigned int y )
00176 {
00177 if( !AS_ASSERT(im) )
00178 {
00179 ASStorageID *part = im->channels[color];
00180 if( color < IC_NUM_CHANNELS )
00181 {
00182 if( part[y] )
00183 {
00184 forget_data( NULL, part[y] );
00185 part[y] = 0;
00186 }
00187 }else
00188 {
00189 int c ;
00190 for( c = 0 ; c < IC_NUM_CHANNELS ; c++ )
00191 {
00192 part = im->channels[c];
00193 if( part[y] )
00194 forget_data( NULL, part[y] );
00195 part[y] = 0;
00196 }
00197 }
00198 }
00199 }
00200
00201
00202
00203 void
00204 copy_component( register CARD32 *src, register CARD32 *dst, int *unused, int len )
00205 {
00206 #if 1
00207 #ifdef CARD64
00208 CARD64 *dsrc = (CARD64*)src;
00209 CARD64 *ddst = (CARD64*)dst;
00210 #else
00211 double *dsrc = (double*)src;
00212 double *ddst = (double*)dst;
00213 #endif
00214 register int i = 0;
00215
00216 len += len&0x01;
00217 len = len>>1 ;
00218 do
00219 {
00220 ddst[i] = dsrc[i];
00221 }while(++i < len );
00222 #else
00223 register int i = 0;
00224
00225 len += len&0x01;
00226 do
00227 {
00228 dst[i] = src[i];
00229 }while(++i < len );
00230 #endif
00231 }
00232
00233 static inline int
00234 set_component( register CARD32 *src, register CARD32 value, int offset, int len )
00235 {
00236 register int i ;
00237 for( i = offset ; i < len ; ++i )
00238 src[i] = value;
00239 return len-offset;
00240 }
00241
00242
00243
00244 static inline void
00245 divide_component( register CARD32 *src, register CARD32 *dst, CARD16 ratio, int len )
00246 {
00247 register int i = 0;
00248 len += len&0x00000001;
00249 if( ratio == 2 )
00250 {
00251 #ifdef HAVE_MMX
00252 if( asimage_use_mmx )
00253 {
00254 #if 1
00255 __m64 *vdst = (__m64*)&(dst[0]);
00256 __m64 *vsrc = (__m64*)&(src[0]);
00257 len = len>>1;
00258 do{
00259 vdst[i] = _mm_srli_pi32(vsrc[i],1);
00260 }while( ++i < len );
00261 _mm_empty();
00262 #else
00263 double *ddst = (double*)&(dst[0]);
00264 double *dsrc = (double*)&(src[0]);
00265 len = len>>1;
00266 do{
00267 asm volatile
00268 (
00269 "movq %1, %%mm0 \n\t"
00270 "psrld $1, %%mm0 \n\t"
00271 "movq %%mm0, %0 \n\t"
00272 : "=m" (ddst[i])
00273 : "m" (dsrc[i])
00274 );
00275 }while( ++i < len );
00276 #endif
00277 }else
00278 #endif
00279 do{
00280 dst[i] = src[i] >> 1;
00281 dst[i+1] = src[i+1]>> 1;
00282 i += 2 ;
00283 }while( i < len );
00284 }else
00285 {
00286 do{
00287 register int c1 = src[i];
00288 register int c2 = src[i+1];
00289 dst[i] = c1/ratio;
00290 dst[i+1] = c2/ratio;
00291 i+=2;
00292 }while( i < len );
00293 }
00294 }
00295
00296
00297
00298 ASImageDecoder *
00299 start_image_decoding( ASVisual *asv,ASImage *im, ASFlagType filter,
00300 int offset_x, int offset_y,
00301 unsigned int out_width,
00302 unsigned int out_height,
00303 ASImageBevel *bevel )
00304 {
00305 ASImageDecoder *imdec = NULL;
00306
00307 if( asv == NULL )
00308 asv = get_default_asvisual();
00309
00310 if( AS_ASSERT(filter) || AS_ASSERT(asv))
00311 return NULL;
00312 if( im != NULL )
00313 if( im->magic != MAGIC_ASIMAGE )
00314 {
00315 #ifdef LOCAL_DEBUG
00316 ASImage **tmp = NULL;
00317 *tmp = im ;
00318 #endif
00319 im = NULL ;
00320 }
00321
00322 if( im == NULL )
00323 {
00324 offset_x = offset_y = 0 ;
00325 if( AS_ASSERT(out_width)|| AS_ASSERT(out_height))
00326 return NULL ;
00327 }else
00328 {
00329 if( offset_x < 0 )
00330 offset_x = (int)im->width + (offset_x%(int)im->width);
00331 else
00332 offset_x %= im->width ;
00333 if( offset_y < 0 )
00334 offset_y = (int)im->height + (offset_y%(int)im->height);
00335 else
00336 offset_y %= im->height ;
00337 if( out_width == 0 )
00338 out_width = im->width ;
00339 if( out_height == 0 )
00340 out_height = im->height ;
00341
00342 }
00343
00344 imdec = safecalloc( 1, sizeof(ASImageDecoder));
00345 imdec->asv = asv ;
00346 imdec->im = im ;
00347 imdec->filter = filter ;
00348 imdec->offset_x = offset_x ;
00349 imdec->out_width = out_width;
00350 imdec->offset_y = offset_y ;
00351 imdec->out_height = out_height;
00352 imdec->next_line = offset_y ;
00353 imdec->back_color = (im != NULL)?im->back_color:ARGB32_DEFAULT_BACK_COLOR ;
00354 imdec->bevel = bevel ;
00355 if( bevel )
00356 {
00357 if( bevel->left_outline > MAX_BEVEL_OUTLINE )
00358 bevel->left_outline = MAX_BEVEL_OUTLINE ;
00359 if( bevel->top_outline > MAX_BEVEL_OUTLINE )
00360 bevel->top_outline = MAX_BEVEL_OUTLINE ;
00361 if( bevel->right_outline > MAX_BEVEL_OUTLINE )
00362 bevel->right_outline = MAX_BEVEL_OUTLINE ;
00363 if( bevel->bottom_outline > MAX_BEVEL_OUTLINE )
00364 bevel->bottom_outline = MAX_BEVEL_OUTLINE ;
00365 if( bevel->left_inline > out_width )
00366 bevel->left_inline = MAX((int)out_width,0) ;
00367 if( bevel->top_inline > out_height )
00368 bevel->top_inline = MAX((int)out_height,0) ;
00369 if( bevel->left_inline+bevel->right_inline > (int)out_width )
00370 bevel->right_inline = MAX((int)out_width-(int)bevel->left_inline,0) ;
00371 if( bevel->top_inline+bevel->bottom_inline > (int)out_height )
00372 bevel->bottom_inline = MAX((int)out_height-(int)bevel->top_inline,0) ;
00373
00374 if( bevel->left_outline == 0 && bevel->right_outline == 0 &&
00375 bevel->top_outline == 0 && bevel->bottom_outline == 0 &&
00376 bevel->left_inline == 0 && bevel->left_inline == 0 &&
00377 bevel->top_inline == 0 && bevel->bottom_inline == 0 )
00378 imdec->bevel = bevel = NULL ;
00379 }
00380 if( bevel )
00381 {
00382 imdec->bevel_left = bevel->left_outline ;
00383 imdec->bevel_top = bevel->top_outline ;
00384 imdec->bevel_right = imdec->bevel_left + (int)out_width ;
00385 imdec->bevel_bottom = imdec->bevel_top + (int)out_height;
00386 imdec->bevel_h_addon = bevel->left_outline+ bevel->right_outline;
00387 imdec->bevel_v_addon = bevel->top_outline + bevel->bottom_outline;
00388
00389 imdec->decode_image_scanline = decode_image_scanline_beveled ;
00390 }else
00391 imdec->decode_image_scanline = decode_image_scanline_normal ;
00392
00393 prepare_scanline(out_width+imdec->bevel_h_addon, 0, &(imdec->buffer), asv->BGR_mode );
00394 imdec->buffer.back_color = (im != NULL)?im->back_color:ARGB32_DEFAULT_BACK_COLOR ;
00395 imdec->buffer.flags = filter;
00396
00397 imdec->decode_asscanline = decode_asscanline_native;
00398 if( im != NULL )
00399 {
00400 if( get_flags( im->flags, ASIM_DATA_NOT_USEFUL ) )
00401 {
00402 if( im->alt.ximage != NULL && !get_flags( im->flags, ASIM_XIMAGE_NOT_USEFUL) )
00403 {
00404 imdec->decode_asscanline = decode_asscanline_ximage;
00405 imdec->xim_buffer = safecalloc(1, sizeof(ASScanline));
00406 prepare_scanline(im->alt.ximage->width, 0, imdec->xim_buffer, asv->BGR_mode );
00407 }else if( im->alt.argb32 != NULL )
00408 {
00409 imdec->decode_asscanline = decode_asscanline_argb32;
00410 }
00411 }
00412 }
00413
00414 return imdec;
00415 }
00416
00417 void
00418 set_decoder_bevel_geom( ASImageDecoder *imdec, int x, int y,
00419 unsigned int width, unsigned int height )
00420 {
00421 if( imdec && imdec->bevel )
00422 {
00423 ASImageBevel *bevel = imdec->bevel ;
00424 int tmp ;
00425 if( imdec->im )
00426 {
00427 if( width == 0 )
00428 width = imdec->im->width ;
00429 if( height == 0 )
00430 height= imdec->im->height;
00431 }else
00432 {
00433 if( width == 0 )
00434 width = MAX( (int)imdec->out_width - x,0) ;
00435 if( height == 0 )
00436 height= MAX( (int)imdec->out_height - y,0) ;
00437 }
00438
00439 x = MIN(x,0);
00440 y = MIN(y,0);
00441 if( x+width < imdec->out_width )
00442 width += (int)imdec->out_width - x ;
00443 if( y+height < imdec->out_height )
00444 height += (int)imdec->out_height - y ;
00445
00446 imdec->bevel_left = x ;
00447 imdec->bevel_top = y ;
00448 imdec->bevel_right = x+(int)width ;
00449 imdec->bevel_bottom = y+(int)height ;
00450
00451
00452 imdec->bevel_h_addon = MAX(imdec->bevel_left+(int)bevel->left_outline, 0) ;
00453 tmp = MAX(0, (int)imdec->out_width - imdec->bevel_right );
00454 imdec->bevel_h_addon += MIN( tmp, (int)bevel->right_outline);
00455
00456 imdec->bevel_v_addon = MAX(imdec->bevel_top+(int)bevel->top_outline, 0) ;
00457 tmp = MAX(0, (int)imdec->out_height - imdec->bevel_bottom );
00458 imdec->bevel_v_addon += MIN( tmp, (int)bevel->bottom_outline);
00459 }
00460 }
00461
00462 void
00463 set_decoder_shift( ASImageDecoder *imdec, int shift )
00464 {
00465 if( shift != 0 )
00466 shift = 8 ;
00467
00468 if( imdec )
00469 imdec->buffer.shift = shift ;
00470 }
00471
00472 void set_decoder_back_color( ASImageDecoder *imdec, ARGB32 back_color )
00473 {
00474 if( imdec )
00475 {
00476 imdec->back_color = back_color ;
00477 imdec->buffer.back_color = back_color ;
00478 }
00479 }
00480
00481
00482 void
00483 stop_image_decoding( ASImageDecoder **pimdec )
00484 {
00485 if( pimdec )
00486 if( *pimdec )
00487 {
00488 free_scanline( &((*pimdec)->buffer), True );
00489 if( (*pimdec)->xim_buffer )
00490 {
00491 free_scanline( (*pimdec)->xim_buffer, True );
00492 free( (*pimdec)->xim_buffer );
00493 }
00494
00495 free( *pimdec );
00496 *pimdec = NULL;
00497 }
00498 }
00499
00500
00501
00502 ASImageOutput *
00503 start_image_output( ASVisual *asv, ASImage *im, ASAltImFormats format,
00504 int shift, int quality )
00505 {
00506 register ASImageOutput *imout= NULL;
00507
00508 if( im != NULL )
00509 if( im->magic != MAGIC_ASIMAGE )
00510 {
00511 im = NULL ;
00512 }
00513
00514 if( asv == NULL )
00515 asv = get_default_asvisual();
00516
00517 if( AS_ASSERT(im) || AS_ASSERT(asv) )
00518 return imout;
00519
00520 if( format < 0 || format == ASA_Vector || format >= ASA_Formats)
00521 return NULL;
00522 if( asimage_format_handlers[format].check_create_asim_format )
00523 if( !asimage_format_handlers[format].check_create_asim_format(asv, im, format) )
00524 return NULL;
00525
00526 imout = safecalloc( 1, sizeof(ASImageOutput));
00527 imout->asv = asv;
00528 imout->im = im ;
00529
00530 imout->out_format = format ;
00531 imout->encode_image_scanline = asimage_format_handlers[format].encode_image_scanline;
00532
00533 prepare_scanline( im->width, 0, &(imout->buffer[0]), asv->BGR_mode);
00534 prepare_scanline( im->width, 0, &(imout->buffer[1]), asv->BGR_mode);
00535
00536 imout->chan_fill[IC_RED] = ARGB32_RED8(im->back_color);
00537 imout->chan_fill[IC_GREEN] = ARGB32_GREEN8(im->back_color);
00538 imout->chan_fill[IC_BLUE] = ARGB32_BLUE8(im->back_color);
00539 imout->chan_fill[IC_ALPHA] = ARGB32_ALPHA8(im->back_color);
00540
00541 imout->available = &(imout->buffer[0]);
00542 imout->used = NULL;
00543 imout->buffer_shift = shift;
00544 imout->next_line = 0 ;
00545 imout->bottom_to_top = 1 ;
00546 if( quality > ASIMAGE_QUALITY_TOP || quality < ASIMAGE_QUALITY_POOR )
00547 quality = asimage_quality_level;
00548
00549 imout->quality = quality ;
00550 if( shift > 0 )
00551 {
00552 switch( quality )
00553 {
00554 case ASIMAGE_QUALITY_POOR :
00555 case ASIMAGE_QUALITY_FAST :
00556 imout->output_image_scanline = output_image_line_fast ;
00557 break;
00558 case ASIMAGE_QUALITY_GOOD :
00559 imout->output_image_scanline = output_image_line_fine ;
00560 break;
00561 case ASIMAGE_QUALITY_TOP :
00562 imout->output_image_scanline = output_image_line_top ;
00563 break;
00564 }
00565 }else
00566 imout->output_image_scanline = output_image_line_direct ;
00567
00568 return imout;
00569 }
00570
00571 void set_image_output_back_color( ASImageOutput *imout, ARGB32 back_color )
00572 {
00573 if( imout )
00574 {
00575 imout->chan_fill[IC_RED] = ARGB32_RED8 (back_color);
00576 imout->chan_fill[IC_GREEN] = ARGB32_GREEN8(back_color);
00577 imout->chan_fill[IC_BLUE] = ARGB32_BLUE8 (back_color);
00578 imout->chan_fill[IC_ALPHA] = ARGB32_ALPHA8(back_color);
00579 }
00580 }
00581
00582 void toggle_image_output_direction( ASImageOutput *imout )
00583 {
00584 if( imout )
00585 {
00586 if( imout->bottom_to_top < 0 )
00587 {
00588 if( imout->next_line >= (int)imout->im->height-1 )
00589 imout->next_line = 0 ;
00590 imout->bottom_to_top = 1 ;
00591 }else if( imout->next_line <= 0 )
00592 {
00593 imout->next_line = (int)imout->im->height-1 ;
00594 imout->bottom_to_top = -1 ;
00595 }
00596 }
00597 }
00598
00599
00600 void
00601 stop_image_output( ASImageOutput **pimout )
00602 {
00603 if( pimout )
00604 {
00605 register ASImageOutput *imout = *pimout;
00606 if( imout )
00607 {
00608 if( imout->used )
00609 imout->output_image_scanline( imout, NULL, 1);
00610 free_scanline(&(imout->buffer[0]), True);
00611 free_scanline(&(imout->buffer[1]), True);
00612 free( imout );
00613 *pimout = NULL;
00614 }
00615 }
00616 }
00617
00618
00619 static inline void
00620 best_output_filter( register CARD32 *line1, register CARD32 *line2, int unused, int len )
00621 {
00622
00623
00624 register int i ;
00625 register CARD32 errp = 0, err = 0, c;
00626 c = line1[0];
00627 if( (c&0xFFFF0000)!= 0 )
00628 c = ( c&0x7F000000 )?0:0x0000FFFF;
00629 errp = c&QUANT_ERR_MASK;
00630 line1[0] = c>>QUANT_ERR_BITS ;
00631 line2[0] += (errp*5)>>4 ;
00632
00633 for( i = 1 ; i < len ; ++i )
00634 {
00635 c = line1[i];
00636 if( (c&0xFFFF0000)!= 0 )
00637 c = (c&0x7F000000)?0:0x0000FFFF;
00638 c += ((errp*7)>>4) ;
00639 err = c&QUANT_ERR_MASK;
00640 line1[i] = (c&0x7FFF0000)?0x000000FF:(c>>QUANT_ERR_BITS);
00641 line2[i-1] += (err*3)>>4 ;
00642 line2[i] += ((err*5)>>4)+(errp>>4);
00643 errp = err ;
00644 }
00645 }
00646
00647 static inline void
00648 fine_output_filter( register CARD32 *src, register CARD32 *dst, short ratio, int len )
00649 {
00650 register int i = 0;
00651 if( ratio <= 1 )
00652 {
00653 register int c = src[0];
00654 do
00655 {
00656 if( (c&0xFFFF0000)!= 0 )
00657 c = ( c&0x7F000000 )?0:0x0000FFFF;
00658 dst[i] = c>>(QUANT_ERR_BITS) ;
00659 if( ++i >= len )
00660 break;
00661 c = ((c&QUANT_ERR_MASK)>>1)+src[i];
00662 }while(1);
00663 }else if( ratio == 2 )
00664 {
00665 register CARD32 c = src[0];
00666 do
00667 {
00668 c = c>>1 ;
00669 if( (c&0xFFFF0000) != 0 )
00670 c = ( c&0x7F000000 )?0:0x0000FFFF;
00671 dst[i] = c>>(QUANT_ERR_BITS) ;
00672 if( ++i >= len )
00673 break;
00674 c = ((c&QUANT_ERR_MASK)>>1)+src[i];
00675 }while( 1 );
00676 }else
00677 {
00678 register CARD32 c = src[0];
00679 do
00680 {
00681 c = c/ratio ;
00682 if( c&0xFFFF0000 )
00683 c = ( c&0x7F000000 )?0:0x0000FFFF;
00684 dst[i] = c>>(QUANT_ERR_BITS) ;
00685 if( ++i >= len )
00686 break;
00687 c = ((c&QUANT_ERR_MASK)>>1)+src[i];
00688 }while(1);
00689 }
00690 }
00691
00692 static inline void
00693 fast_output_filter( register CARD32 *src, register CARD32 *dst, short ratio, int len )
00694 {
00695 register int i = 0;
00696 if( ratio <= 1 )
00697 {
00698 for( ; i < len ; ++i )
00699 {
00700 register CARD32 c = src[i];
00701 if( (c&0xFFFF0000) != 0 )
00702 dst[i] = ( c&0x7F000000 )?0:0x000000FF;
00703 else
00704 dst[i] = c>>(QUANT_ERR_BITS) ;
00705 }
00706 }else if( ratio == 2 )
00707 {
00708 for( ; i < len ; ++i )
00709 {
00710 register CARD32 c = src[i]>>1;
00711 if( (c&0xFFFF0000) != 0 )
00712 dst[i] = ( c&0x7F000000 )?0:0x000000FF;
00713 else
00714 dst[i] = c>>(QUANT_ERR_BITS) ;
00715 }
00716 }else
00717 {
00718 for( ; i < len ; ++i )
00719 {
00720 register CARD32 c = src[i]/ratio;
00721 if( (c&0xFFFF0000) != 0 )
00722 dst[i] = ( c&0x7F000000 )?0:0x000000FF;
00723 else
00724 dst[i] = c>>(QUANT_ERR_BITS) ;
00725 }
00726 }
00727 }
00728
00729 static inline void
00730 fine_output_filter_mod( register CARD32 *data, int unused, int len )
00731 {
00732 register int i ;
00733 register CARD32 err = 0, c;
00734 for( i = 0 ; i < len ; ++i )
00735 {
00736 c = data[i];
00737 if( (c&0xFFFF0000) != 0 )
00738 c = ( c&0x7E000000 )?0:0x0000FFFF;
00739 c += err;
00740 err = (c&QUANT_ERR_MASK)>>1 ;
00741 data[i] = (c&0x00FF0000)?0x000000FF:c>>QUANT_ERR_BITS ;
00742 }
00743 }
00744
00745
00746
00747
00748 static void
00749 decode_asscanline_native( ASImageDecoder *imdec, unsigned int skip, int y )
00750 {
00751 int i ;
00752 ASScanline *scl = &(imdec->buffer);
00753 int count, width = scl->width-skip ;
00754 for( i = 0 ; i < IC_NUM_CHANNELS ; i++ )
00755 if( get_flags(imdec->filter, 0x01<<i) )
00756 {
00757 register CARD32 *chan = scl->channels[i]+skip;
00758 if( imdec->im )
00759 count = fetch_data32( NULL, imdec->im->channels[i][y], chan, imdec->offset_x, width, 0, NULL);
00760 else
00761 count = 0 ;
00762 if( scl->shift )
00763 {
00764 register int k = 0;
00765 for(; k < count ; k++ )
00766 chan[k] = chan[k]<<8;
00767 }
00768 if( count < width )
00769 set_component( chan, ARGB32_CHAN8(imdec->back_color, i)<<scl->shift, count, width );
00770 }
00771 clear_flags( scl->flags, SCL_DO_ALL);
00772 set_flags( scl->flags, imdec->filter);
00773 }
00774
00775 static void
00776 decode_asscanline_argb32( ASImageDecoder *imdec, unsigned int skip, int y )
00777 {
00778 ASScanline *scl = &(imdec->buffer);
00779 int count, width = scl->width-skip ;
00780 ARGB32 *row = imdec->im->alt.argb32 + y*imdec->im->width ;
00781 CARD32 *a = scl->alpha+skip;
00782 CARD32 *r = scl->red+skip;
00783 CARD32 *g = scl->green+skip;
00784 CARD32 *b = scl->blue+skip;
00785 int max_x = imdec->im->width ;
00786
00787 if( get_flags( imdec->filter, SCL_DO_ALPHA ) )
00788 {
00789 int x = imdec->offset_x ;
00790 for( count = 0 ; count < width ; ++count)
00791 {
00792 a[count] = ARGB32_ALPHA8(row[x])<<scl->shift ;
00793 if( ++x >= max_x ) x = 0;
00794 }
00795 }
00796
00797 if( get_flags( imdec->filter, SCL_DO_RED ) )
00798 {
00799 int x = imdec->offset_x ;
00800 for( count = 0 ; count < width ; ++count)
00801 {
00802 r[count] = ARGB32_RED8(row[x])<<scl->shift ;
00803 if( ++x >= max_x ) x = 0;
00804 }
00805 }
00806
00807 if( get_flags( imdec->filter, SCL_DO_GREEN ) )
00808 {
00809 int x = imdec->offset_x ;
00810 for( count = 0 ; count < width ; ++count)
00811 {
00812 g[count] = ARGB32_GREEN8(row[x])<<scl->shift ;
00813 if( ++x >= max_x ) x = 0;
00814 }
00815 }
00816 if( get_flags( imdec->filter, SCL_DO_BLUE ) )
00817 {
00818 int x = imdec->offset_x ;
00819 for( count = 0 ; count < width ; ++count)
00820 {
00821 b[count] = ARGB32_BLUE8(row[x])<<scl->shift ;
00822 if( ++x >= max_x ) x = 0;
00823 }
00824 }
00825
00826 clear_flags( scl->flags, SCL_DO_ALL);
00827 set_flags( scl->flags, imdec->filter);
00828 }
00829
00830
00831 static void
00832 decode_asscanline_ximage( ASImageDecoder *imdec, unsigned int skip, int y )
00833 {
00834 int i ;
00835 ASScanline *scl = &(imdec->buffer);
00836 XImage *xim = imdec->im->alt.ximage ;
00837 int count, width = scl->width-skip, xim_width = xim->width ;
00838 ASFlagType filter = imdec->filter ;
00839 #if 1
00840 if( width > xim_width || imdec->offset_x > 0 )
00841 {
00842 ASScanline *xim_scl = imdec->xim_buffer;
00843 int offset_x = imdec->offset_x%xim_width ;
00844
00845
00846 GET_SCANLINE(imdec->asv,xim,xim_scl,y,(unsigned char*)xim->data+xim->bytes_per_line*y);
00847
00848 if( (xim = imdec->im->alt.mask_ximage ) != NULL )
00849 {
00850 #ifndef X_DISPLAY_MISSING
00851 CARD32 *dst = xim_scl->alpha ;
00852 register int x = MIN((int)xim_scl->width,xim->width);
00853 if( xim->depth == 8 )
00854 {
00855 CARD8 *src = (CARD8*)xim->data+xim->bytes_per_line*y ;
00856 while(--x >= 0 ) dst[x] = (CARD32)(src[x]);
00857 }else
00858 {
00859 while(--x >= 0 ) dst[x] = (XGetPixel(xim, x, y) == 0)?0x00:0xFF;
00860 }
00861 #endif
00862 }
00863 for( i = 0 ; i < IC_NUM_CHANNELS ; i++ )
00864 if( get_flags(filter, 0x01<<i) )
00865 {
00866 register CARD32 *src = xim_scl->channels[i]+offset_x ;
00867 register CARD32 *dst = scl->channels[i]+skip;
00868 register int k = 0;
00869 count = xim_width-offset_x ;
00870 if( count > width )
00871 count = width ;
00872
00873 #define COPY_TILE_CHAN(op) \
00874 for(; k < count ; k++ ) dst[k] = op; \
00875 while( k < width ) \
00876 { src = xim_scl->channels[i]-k ; \
00877 count = MIN(xim_width+k,width); \
00878 for(; k < count ; k++ ) dst[k] = op; \
00879 }
00880
00881 if( scl->shift )
00882 {
00883 COPY_TILE_CHAN(src[k]<<8)
00884 }else
00885 {
00886 COPY_TILE_CHAN(src[k])
00887 }
00888 count += k ;
00889 if( count < width )
00890 set_component( src, ARGB32_CHAN8(imdec->back_color, i)<<scl->shift, count, width );
00891 }
00892 }else
00893 #endif
00894 {
00895
00896 int old_offset = scl->offset_x ;
00897 scl->offset_x = skip ;
00898 GET_SCANLINE(imdec->asv,xim,scl,y,(unsigned char *)xim->data+xim->bytes_per_line*y);
00899
00900 if( (xim = imdec->im->alt.mask_ximage ) != NULL )
00901 {
00902 #ifndef X_DISPLAY_MISSING
00903 CARD32 *dst = scl->alpha+skip ;
00904 register int x = MIN(width,xim_width);
00905 if( xim->depth == 8 )
00906 {
00907 CARD8 *src = (CARD8*)xim->data+xim->bytes_per_line*y ;
00908 while(--x >= 0 ) dst[x] = (CARD32)(src[x]);
00909 }else
00910 {
00911 while(--x >= 0 ) dst[x] = (XGetPixel(xim, x, y) == 0)?0x00:0xFF;
00912 }
00913 #endif
00914 }
00915 count = MIN(width,xim_width);
00916 scl->offset_x = old_offset ;
00917 for( i = 0 ; i < IC_NUM_CHANNELS ; i++ )
00918 if( get_flags(filter, 0x01<<i) )
00919 {
00920 register CARD32 *chan = scl->channels[i]+skip;
00921 if( scl->shift )
00922 {
00923 register int k = 0;
00924 for(; k < count ; k++ )
00925 chan[k] = chan[k]<<8;
00926 }
00927 if( count < width )
00928 set_component( chan, ARGB32_CHAN8(imdec->back_color, i)<<scl->shift, count, width );
00929 }
00930 }
00931 clear_flags( scl->flags,SCL_DO_ALL);
00932 set_flags( scl->flags,imdec->filter);
00933 }
00934
00935
00936
00937 void
00938 decode_image_scanline_normal( ASImageDecoder *imdec )
00939 {
00940 int y = imdec->next_line;
00941 if( y - imdec->offset_y >= imdec->out_height )
00942 {
00943 imdec->buffer.flags = 0 ;
00944 imdec->buffer.back_color = imdec->back_color ;
00945 return ;
00946 }
00947
00948 if( imdec->im )
00949 y %= imdec->im->height;
00950 imdec->decode_asscanline( imdec, 0, y );
00951 ++(imdec->next_line);
00952 }
00953
00954 static inline void
00955 draw_solid_bevel_line( register ASScanline *scl, int alt_left, int hi_end, int lo_start, int alt_right,
00956 ARGB32 bevel_color, ARGB32 shade_color, ARGB32 hi_corner, ARGB32 lo_corner )
00957 {
00958 int channel ;
00959 for( channel = 0 ; channel < ARGB32_CHANNELS ; ++channel )
00960 if( get_flags(scl->flags, (0x01<<channel)) )
00961 {
00962 if( hi_end > 0 )
00963 {
00964 set_component( scl->channels[channel],
00965 ARGB32_CHAN8(bevel_color,channel)<<scl->shift,
00966 0, hi_end );
00967 if( alt_left > 0 )
00968 scl->channels[channel][alt_left-1] =
00969 ARGB32_CHAN8(hi_corner,channel)<<scl->shift ;
00970 }
00971 if( lo_start < (int)scl->width )
00972 {
00973 set_component( scl->channels[channel],
00974 ARGB32_CHAN8(shade_color,channel)<<scl->shift,
00975 lo_start, scl->width );
00976 if( alt_right < (int)scl->width && alt_right > 0 )
00977 scl->channels[channel][scl->width - alt_right] =
00978 ARGB32_CHAN8(lo_corner,channel)<<scl->shift ;
00979 }
00980 }
00981 }
00982 static inline void
00983 draw_fading_bevel_sides( ASImageDecoder *imdec,
00984 int left_margin, int left_delta,
00985 int right_delta, int right_margin )
00986 {
00987 register ASScanline *scl = &(imdec->buffer);
00988 ASImageBevel *bevel = imdec->bevel ;
00989 CARD32 ha_bevel = ARGB32_ALPHA8(bevel->hi_color);
00990 CARD32 ha_shade = ARGB32_ALPHA8(bevel->lo_color);
00991 CARD32 hda_bevel = (ha_bevel<<8)/(bevel->left_inline+1) ;
00992 CARD32 hda_shade = (ha_shade<<8)/(bevel->right_inline+1);
00993 int channel ;
00994
00995 for( channel = 0 ; channel < ARGB32_CHANNELS ; ++channel )
00996 if( get_flags(scl->flags, (0x01<<channel)) )
00997 {
00998 CARD32 chan_col = ARGB32_CHAN8(bevel->hi_color,channel)<<scl->shift ;
00999 register CARD32 ca = hda_bevel*(left_delta+1) ;
01000 register int i = MIN((int)scl->width, imdec->bevel_left+(int)bevel->left_inline-left_delta);
01001 CARD32 *chan_img_start = scl->channels[channel] ;
01002
01003 while( --i >= left_margin )
01004 {
01005 chan_img_start[i] = (chan_img_start[i]*(255-(ca>>8))+chan_col*(ca>>8))>>8 ;
01006 ca += hda_bevel ;
01007 }
01008 ca = hda_shade*(right_delta+1) ;
01009 i = MAX( left_margin, imdec->bevel_right + right_delta - (int)bevel->right_inline);
01010 chan_col = ARGB32_CHAN8(bevel->lo_color,channel)<<scl->shift ;
01011 while( ++i < right_margin )
01012 {
01013 chan_img_start[i] = (chan_img_start[i]*(255-(ca>>8))+chan_col*(ca>>8))>>8 ;
01014 ca += hda_shade ;
01015 }
01016 }
01017 }
01018
01019 static inline void
01020 draw_transp_bevel_sides( ASImageDecoder *imdec,
01021 int left_margin, int left_delta,
01022 int right_delta, int right_margin )
01023 {
01024 register ASScanline *scl = &(imdec->buffer);
01025 ASImageBevel *bevel = imdec->bevel ;
01026 CARD32 ha_bevel = ARGB32_ALPHA8(bevel->hi_color)>>1;
01027 CARD32 ha_shade = ARGB32_ALPHA8(bevel->lo_color)>>1;
01028 int channel ;
01029
01030 for( channel = 0 ; channel < ARGB32_CHANNELS ; ++channel )
01031 if( get_flags(scl->flags, (0x01<<channel)) )
01032 {
01033 CARD32 chan_col = (ARGB32_CHAN8(bevel->hi_color,channel)<<scl->shift)*ha_bevel ;
01034 register CARD32 ca = 255-ha_bevel ;
01035 register int i = imdec->bevel_left+(int)bevel->left_inline-left_delta;
01036 CARD32 *chan_img_start = scl->channels[channel] ;
01037
01038 while( --i >= left_margin )
01039 chan_img_start[i] = (chan_img_start[i]*ca+chan_col)>>8 ;
01040
01041 ca = 255-ha_shade ;
01042 i = MAX( left_margin, imdec->bevel_right + right_delta - (int)bevel->right_inline);
01043 chan_col = (ARGB32_CHAN8(bevel->lo_color,channel)<<scl->shift)*ha_shade ;
01044 while( ++i < right_margin )
01045 chan_img_start[i] = (chan_img_start[i]*ca+chan_col)>>8 ;
01046 }
01047 }
01048
01049
01050 static inline void
01051 draw_transp_bevel_line ( ASImageDecoder *imdec,
01052 int left_delta, int right_delta,
01053 CARD32 ca,
01054 ARGB32 left_color, ARGB32 color, ARGB32 right_color )
01055 {
01056 register ASScanline *scl = &(imdec->buffer);
01057 ASImageBevel *bevel = imdec->bevel ;
01058 int start_point = imdec->bevel_left+(int)bevel->left_inline-left_delta;
01059 int end_point = imdec->bevel_right + right_delta - (int)bevel->right_inline;
01060 int channel ;
01061 CARD32 rev_ca = (255-(ca>>8));
01062 if( start_point < (int)scl->width && end_point > 0 )
01063 {
01064 for( channel = 0 ; channel < ARGB32_CHANNELS ; ++channel )
01065 if( get_flags(scl->flags, (0x01<<channel)) )
01066 {
01067 CARD32 chan_col = (ARGB32_CHAN8(color,channel)<<scl->shift)*(ca>>8) ;
01068 CARD32 *chan_img_start = scl->channels[channel] ;
01069 register int i ;
01070 int end_i;
01071
01072 if( start_point < 0 )
01073 i = -1 ;
01074 else
01075 {
01076 i = start_point-1 ;
01077 if( i < (int)scl->width && i >= 0 )
01078 chan_img_start[i] = (chan_img_start[i]*rev_ca + ARGB32_CHAN8(left_color,channel)*(ca>>8))>>8 ;
01079 }
01080 if( end_point >= (int)scl->width )
01081 end_i = scl->width ;
01082 else
01083 {
01084 end_i = end_point ;
01085 if( end_i >= 0 )
01086 chan_img_start[end_i] = (chan_img_start[end_i]*rev_ca + ARGB32_CHAN8(right_color,channel)*(ca>>8))>>8 ;
01087 }
01088 while( ++i < end_i )
01089 chan_img_start[i] = (chan_img_start[i]*rev_ca+chan_col)>>8;
01090 }
01091 }
01092 }
01093
01094 void
01095 decode_image_scanline_beveled( ASImageDecoder *imdec )
01096 {
01097 register ASScanline *scl = &(imdec->buffer);
01098 int y_out = imdec->next_line- (int)imdec->offset_y;
01099 register ASImageBevel *bevel = imdec->bevel ;
01100 ARGB32 bevel_color = bevel->hi_color, shade_color = bevel->lo_color;
01101 int offset_shade = 0;
01102
01103 scl->flags = 0 ;
01104 if( y_out < 0 || y_out > (int)imdec->out_height+imdec->bevel_v_addon )
01105 {
01106 scl->back_color = imdec->back_color ;
01107 return ;
01108 }
01109
01110
01111 set_flags( scl->flags, imdec->filter );
01112 if( y_out < imdec->bevel_top )
01113 {
01114 if( bevel->top_outline > 0 )
01115 {
01116 register int line = y_out - (imdec->bevel_top - (int)bevel->top_outline);
01117 int alt_left = (line*bevel->left_outline/bevel->top_outline)+1 ;
01118 int alt_right = (line*bevel->right_outline/bevel->top_outline)+1 ;
01119
01120 alt_left += MAX(imdec->bevel_left-(int)bevel->left_outline,0) ;
01121 offset_shade = MAX(imdec->bevel_right+(int)bevel->right_outline-alt_right,0);
01122
01123
01124
01125
01126 if( (int)scl->width < imdec->bevel_right )
01127 alt_right -= imdec->bevel_right-(int)scl->width ;
01128 if( offset_shade > (int)scl->width )
01129 offset_shade = scl->width ;
01130 draw_solid_bevel_line( scl, alt_left, offset_shade, offset_shade, alt_right,
01131 bevel->hi_color, bevel->lo_color, bevel->hihi_color, bevel->hilo_color );
01132 }
01133 }else if( y_out >= imdec->bevel_bottom )
01134 {
01135 if( bevel->bottom_outline > 0 )
01136 {
01137 register int line = bevel->bottom_outline - (y_out - imdec->bevel_bottom);
01138 int alt_left = (line*bevel->left_outline/bevel->bottom_outline)+1 ;
01139 int alt_right = (line*bevel->right_outline/bevel->bottom_outline)+1 ;
01140
01141 alt_left += MAX(imdec->bevel_left-(int)bevel->left_outline,0) ;
01142 offset_shade = MIN(alt_left, (int)scl->width );
01143
01144 if( (int)scl->width < imdec->bevel_right )
01145 alt_right -= imdec->bevel_right-(int)scl->width ;
01146
01147
01148
01149
01150 set_flags( scl->flags, imdec->filter );
01151 draw_solid_bevel_line( scl, alt_left, alt_left, alt_left, alt_right,
01152 bevel->hi_color, bevel->lo_color,
01153 bevel->hilo_color, bevel->lolo_color );
01154 }
01155 }else
01156 {
01157 int left_margin = MAX(0, imdec->bevel_left);
01158 int right_margin = MIN((int)scl->width, imdec->bevel_right);
01159 int y = imdec->next_line-bevel->top_outline ;
01160 if( imdec->im )
01161 y %= imdec->im->height ;
01162
01163 if( left_margin < (int)scl->width )
01164 imdec->decode_asscanline( imdec, left_margin, y );
01165
01166 draw_solid_bevel_line( scl, -1, left_margin, right_margin, scl->width,
01167 bevel->hi_color, bevel->lo_color,
01168 bevel->hilo_color, bevel->lolo_color );
01169 if( left_margin < (int)scl->width )
01170 {
01171 if( get_flags( bevel->type, BEVEL_SOLID_INLINE ) )
01172 {
01173 if( y_out < imdec->bevel_top+(int)bevel->top_inline)
01174 {
01175 register int line = y_out - imdec->bevel_top;
01176 int left_delta = bevel->left_inline-((line*bevel->left_inline/bevel->top_inline)) ;
01177 int right_delta = bevel->right_inline-((line*bevel->right_inline/bevel->top_inline)-1) ;
01178
01179 draw_transp_bevel_sides( imdec, left_margin, left_delta,
01180 right_delta, right_margin );
01181 draw_transp_bevel_line ( imdec, left_delta-1, right_delta-1,
01182 ARGB32_ALPHA8(bevel_color)<<7,
01183 bevel->hihi_color, bevel->hi_color, bevel->hilo_color );
01184
01185 }else if( y_out >= imdec->bevel_bottom - bevel->bottom_inline)
01186 {
01187 register int line = y_out - (imdec->bevel_bottom - bevel->bottom_inline);
01188 int left_delta = (line*bevel->left_inline/bevel->bottom_inline)+1 ;
01189 int right_delta = (line*bevel->right_inline/bevel->bottom_inline)-1 ;
01190
01191 draw_transp_bevel_sides( imdec, left_margin, left_delta,
01192 right_delta, right_margin );
01193 draw_transp_bevel_line ( imdec, left_delta-1, right_delta,
01194 ARGB32_ALPHA8(shade_color)<<7,
01195 bevel->hilo_color, bevel->lo_color, bevel->lolo_color );
01196
01197 }else
01198 {
01199 draw_transp_bevel_sides( imdec, left_margin, 0, 0, right_margin );
01200 }
01201
01202 }
01203 else
01204 {
01205
01206
01207
01208
01209 if( y_out < imdec->bevel_top+bevel->top_inline)
01210 {
01211 register int line = y_out - imdec->bevel_top;
01212 int left_delta = bevel->left_inline-((line*bevel->left_inline/bevel->top_inline)) ;
01213 int right_delta = bevel->right_inline-((line*bevel->right_inline/bevel->top_inline)-1) ;
01214 CARD32 hda_bevel = (ARGB32_ALPHA8(bevel_color)<<8)/(bevel->left_inline+1) ;
01215
01216 draw_fading_bevel_sides( imdec, left_margin, left_delta,
01217 right_delta, right_margin );
01218
01219
01220
01221
01222 draw_transp_bevel_line ( imdec, left_delta-1, right_delta-1,
01223 hda_bevel*(left_delta+1),
01224 bevel->hihi_color, bevel->hi_color, bevel->hilo_color );
01225
01226 }else if( y_out >= imdec->bevel_bottom - bevel->bottom_inline)
01227 {
01228 register int line = y_out - (imdec->bevel_bottom - bevel->bottom_inline);
01229 int left_delta = (line*bevel->left_inline/bevel->bottom_inline)+1 ;
01230 int right_delta = (line*bevel->right_inline/bevel->bottom_inline)-1 ;
01231 CARD32 hda_shade = (ARGB32_ALPHA8(shade_color)<<8)/(bevel->right_inline+1) ;
01232
01233 draw_fading_bevel_sides( imdec, left_margin, left_delta,
01234 right_delta, right_margin );
01235
01236 draw_transp_bevel_line ( imdec, left_delta-1, right_delta,
01237 hda_shade*(right_delta+1),
01238 bevel->hilo_color, bevel->lo_color, bevel->lolo_color );
01239 }else
01240 {
01241 draw_fading_bevel_sides( imdec, left_margin, 0, 0, right_margin );
01242 }
01243 }
01244 }
01245 }
01246 ++(imdec->next_line);
01247 }
01248
01249
01250
01251 inline static void
01252 tile_ximage_line( XImage *xim, unsigned int line, int step, int range )
01253 {
01254 register int i ;
01255 int xim_step = step*xim->bytes_per_line ;
01256 char *src_line = xim->data+xim->bytes_per_line*line ;
01257 char *dst_line = src_line+xim_step ;
01258 int max_i = MIN((int)xim->height,(int)line+range), min_i = MAX(0,(int)line-range) ;
01259 for( i = line+step ; i < max_i && i >= min_i ; i+=step )
01260 {
01261 memcpy( dst_line, src_line, xim->bytes_per_line );
01262 dst_line += xim_step ;
01263 }
01264 }
01265
01266 void
01267 encode_image_scanline_mask_xim( ASImageOutput *imout, ASScanline *to_store )
01268 {
01269 #ifndef X_DISPLAY_MISSING
01270 ASImage *im = imout->im ;
01271 register XImage *xim = im->alt.mask_ximage ;
01272 if( imout->next_line < xim->height && imout->next_line >= 0 )
01273 {
01274 if( get_flags(to_store->flags, SCL_DO_ALPHA) )
01275 {
01276 CARD32 *a = to_store->alpha ;
01277 register int x = MIN((unsigned int)(xim->width), to_store->width);
01278 if( xim->depth == 8 )
01279 {
01280 CARD8 *dst = (CARD8*)xim->data+xim->bytes_per_line*imout->next_line ;
01281 while( --x >= 0 )
01282 dst[x] = (CARD8)(a[x]);
01283 }else
01284 {
01285 unsigned int nl = imout->next_line ;
01286 while( --x >= 0 )
01287 XPutPixel( xim, x, nl, (a[x] >= 0x7F)?1:0 );
01288 }
01289 }
01290 if( imout->tiling_step > 0 )
01291 tile_ximage_line( xim, imout->next_line,
01292 imout->bottom_to_top*imout->tiling_step,
01293 (imout->tiling_range ? imout->tiling_range:imout->im->height) );
01294 imout->next_line += imout->bottom_to_top;
01295 }
01296 #endif
01297 }
01298
01299 void
01300 encode_image_scanline_xim( ASImageOutput *imout, ASScanline *to_store )
01301 {
01302 #ifndef X_DISPLAY_MISSING
01303 register XImage *xim = imout->im->alt.ximage ;
01304 if( imout->next_line < xim->height && imout->next_line >= 0 )
01305 {
01306 unsigned char *dst = (unsigned char*)xim->data+imout->next_line*xim->bytes_per_line ;
01307 if( !get_flags(to_store->flags, SCL_DO_RED) )
01308 set_component( to_store->red, ARGB32_RED8(to_store->back_color), 0, to_store->width );
01309 if( !get_flags(to_store->flags, SCL_DO_GREEN) )
01310 set_component( to_store->green, ARGB32_GREEN8(to_store->back_color), 0, to_store->width );
01311 if( !get_flags(to_store->flags, SCL_DO_BLUE) )
01312 set_component( to_store->blue , ARGB32_BLUE8(to_store->back_color), 0, to_store->width );
01313 if( !get_flags(to_store->flags, SCL_DO_ALPHA) && (xim->depth == 24 || xim->depth == 32 ))
01314 set_component( to_store->alpha , ARGB32_ALPHA8(to_store->back_color), 0, to_store->width );
01315 if( xim->depth == imout->asv->visual_info.depth )
01316 PUT_SCANLINE(imout->asv, xim,to_store,imout->next_line, dst );
01317 else if( xim->depth == 16 )
01318 scanline2ximage16( imout->asv, xim, to_store,imout->next_line, dst);
01319 else if( xim->depth == 24 || xim->depth == 32 )
01320 scanline2ximage32( imout->asv, xim, to_store,imout->next_line, dst);
01321 else if( xim->depth == 15 )
01322 scanline2ximage15( imout->asv, xim, to_store,imout->next_line, dst);
01323
01324
01325 if( imout->tiling_step > 0 )
01326 tile_ximage_line( imout->im->alt.ximage, imout->next_line,
01327 imout->bottom_to_top*imout->tiling_step,
01328 (imout->tiling_range ? imout->tiling_range:imout->im->height) );
01329 LOCAL_DEBUG_OUT( "flags = %lX", to_store->flags );
01330 #if 1
01331 if( imout->out_format == ASA_ScratchXImageAndAlpha )
01332 {
01333 if( get_flags(to_store->flags, SCL_DO_ALPHA) && get_flags( imout->im->flags, ASIM_DATA_NOT_USEFUL ))
01334 {
01335 int bytes_count, i ;
01336 int line = imout->next_line ;
01337 bytes_count = asimage_add_line(imout->im, IC_ALPHA, to_store->channels[IC_ALPHA]+to_store->offset_x, line);
01338 if( imout->tiling_step > 0 )
01339 {
01340 int range = (imout->tiling_range ? imout->tiling_range:imout->im->height);
01341 int max_i = MIN((int)imout->im->height,line+range), min_i = MAX(0,line-range) ;
01342 int step = imout->bottom_to_top*imout->tiling_step;
01343 for( i = line+step ; i < max_i && i >= min_i ; i+=step )
01344 {
01345
01346 asimage_dup_line( imout->im, IC_ALPHA, line, i, bytes_count );
01347 }
01348 }
01349 }
01350 }
01351 #endif
01352 imout->next_line += imout->bottom_to_top;
01353 }
01354 #endif
01355 }
01356
01357 void
01358 encode_image_scanline_asim( ASImageOutput *imout, ASScanline *to_store )
01359 {
01360 LOCAL_DEBUG_CALLER_OUT( "imout->next_line = %d, imout->im->height = %d", imout->next_line, imout->im->height );
01361 if( imout->next_line < (int)imout->im->height && imout->next_line >= 0 )
01362 {
01363 CARD8 chan_fill[4];
01364 chan_fill[IC_RED] = ARGB32_RED8 (to_store->back_color);
01365 chan_fill[IC_GREEN] = ARGB32_GREEN8(to_store->back_color);
01366 chan_fill[IC_BLUE] = ARGB32_BLUE8 (to_store->back_color);
01367 chan_fill[IC_ALPHA] = ARGB32_ALPHA8(to_store->back_color);
01368 if( imout->tiling_step > 0 )
01369 {
01370 int bytes_count ;
01371 register int i, color ;
01372 int line = imout->next_line ;
01373 int range = (imout->tiling_range ? imout->tiling_range:imout->im->height);
01374 int max_i = MIN((int)imout->im->height,line+range), min_i = MAX(0,line-range) ;
01375 int step = imout->bottom_to_top*imout->tiling_step;
01376
01377 for( color = 0 ; color < IC_NUM_CHANNELS ; color++ )
01378 {
01379 if( get_flags(to_store->flags,0x01<<color))
01380 bytes_count = asimage_add_line(imout->im, color, to_store->channels[color]+to_store->offset_x, line);
01381 else if( chan_fill[color] != imout->chan_fill[color] )
01382 bytes_count = asimage_add_line_mono( imout->im, color, (CARD8)chan_fill[color], line);
01383 else
01384 {
01385 asimage_erase_line( imout->im, color, line );
01386 for( i = line+step ; i < max_i && i >= min_i ; i+=step )
01387 asimage_erase_line( imout->im, color, i );
01388 continue;
01389 }
01390 for( i = line+step ; i < max_i && i >= min_i ; i+=step )
01391 {
01392
01393 asimage_dup_line( imout->im, color, line, i, bytes_count );
01394 }
01395 }
01396 }else
01397 {
01398 register int color ;
01399 for( color = 0 ; color < IC_NUM_CHANNELS ; color++ )
01400 {
01401 if( get_flags(to_store->flags,0x01<<color))
01402 {
01403 LOCAL_DEBUG_OUT( "encoding line %d for component %d offset = %d ", imout->next_line, color, to_store->offset_x );
01404 asimage_add_line(imout->im, color, to_store->channels[color]+to_store->offset_x, imout->next_line);
01405 }else if( chan_fill[color] != imout->chan_fill[color] )
01406 {
01407 LOCAL_DEBUG_OUT( "filling line %d for component %d with value %X", imout->next_line, color, chan_fill[color] );
01408 asimage_add_line_mono( imout->im, color, chan_fill[color], imout->next_line);
01409 }else
01410 {
01411 LOCAL_DEBUG_OUT( "erasing line %d for component %d", imout->next_line, color );
01412 asimage_erase_line( imout->im, color, imout->next_line );
01413 }
01414 }
01415 }
01416 }
01417 imout->next_line += imout->bottom_to_top;
01418 }
01419
01420 inline static void
01421 tile_argb32_line( ARGB32 *data, unsigned int line, int step, unsigned int width, unsigned int height, int range )
01422 {
01423 register int i ;
01424 ARGB32 *src_line = data+line*width ;
01425 ARGB32 *dst_line = src_line+step*width ;
01426 int max_i = MIN((int)height,(int)line+range), min_i = MAX(0,(int)line-range) ;
01427
01428 for( i = line+step ; i < max_i && i >= min_i ; i+=step )
01429 {
01430 memcpy( dst_line, src_line, width*sizeof(ARGB32));
01431 dst_line += step*width;
01432 }
01433 }
01434
01435 void
01436 encode_image_scanline_argb32( ASImageOutput *imout, ASScanline *to_store )
01437 {
01438 register ARGB32 *data = imout->im->alt.argb32 ;
01439 if( imout->next_line < (int)imout->im->height && imout->next_line >= 0 )
01440 {
01441 register int x = imout->im->width;
01442 register CARD32 *alpha = to_store->alpha ;
01443 register CARD32 *red = to_store->red ;
01444 register CARD32 *green = to_store->green ;
01445 register CARD32 *blue = to_store->blue ;
01446 if( !get_flags(to_store->flags, SCL_DO_RED) )
01447 set_component( red, ARGB32_RED8(to_store->back_color), 0, to_store->width );
01448 if( !get_flags(to_store->flags, SCL_DO_GREEN) )
01449 set_component( green, ARGB32_GREEN8(to_store->back_color), 0, to_store->width );
01450 if( !get_flags(to_store->flags, SCL_DO_BLUE) )
01451 set_component( blue , ARGB32_BLUE8(to_store->back_color), 0, to_store->width );
01452
01453 data += x*imout->next_line ;
01454 if( !get_flags(to_store->flags, SCL_DO_ALPHA) )
01455 while( --x >= 0 )
01456 data[x] = MAKE_ARGB32( 0xFF, red[x], green[x], blue[x] );
01457 else
01458 while( --x >= 0 )
01459 data[x] = MAKE_ARGB32( alpha[x], red[x], green[x], blue[x] );
01460
01461 if( imout->tiling_step > 0 )
01462 tile_argb32_line( imout->im->alt.argb32, imout->next_line,
01463 imout->bottom_to_top*imout->tiling_step,
01464 imout->im->width, imout->im->height,
01465 (imout->tiling_range ? imout->tiling_range:imout->im->height));
01466 imout->next_line += imout->bottom_to_top;
01467 }
01468 }
01469
01470
01471 void
01472 output_image_line_top( ASImageOutput *imout, ASScanline *new_line, int ratio )
01473 {
01474 ASScanline *to_store = NULL ;
01475
01476 if( new_line )
01477 {
01478 if( ratio > 1 )
01479 SCANLINE_FUNC_FILTERED(divide_component,*(new_line),*(imout->available),(CARD8)ratio,imout->available->width);
01480 else
01481 SCANLINE_FUNC_FILTERED(copy_component,*(new_line),*(imout->available),NULL,imout->available->width);
01482 imout->available->flags = new_line->flags ;
01483 imout->available->back_color = new_line->back_color ;
01484 }
01485
01486 if( imout->used != NULL )
01487 {
01488 if( new_line != NULL )
01489 SCANLINE_FUNC_FILTERED(best_output_filter,*(imout->used),*(imout->available),0,imout->available->width);
01490 else
01491 SCANLINE_MOD_FILTERED(fine_output_filter_mod,*(imout->used),0,imout->used->width);
01492 to_store = imout->used ;
01493 }
01494 if( to_store )
01495 {
01496 imout->encode_image_scanline( imout, to_store );
01497 }
01498
01499 if( imout->buffer_shift > 0 )
01500 {
01501 if( new_line == NULL )
01502 imout->used = NULL ;
01503 else
01504 imout->used = imout->available ;
01505 imout->available = &(imout->buffer[0]);
01506 if( imout->available == imout->used )
01507 imout->available = &(imout->buffer[1]);
01508 }
01509 }
01510
01511 void
01512 output_image_line_fine( ASImageOutput *imout, ASScanline *new_line, int ratio )
01513 {
01514
01515 if( new_line )
01516 {
01517 SCANLINE_FUNC_FILTERED(fine_output_filter, *(new_line),*(imout->available),(CARD8)ratio,imout->available->width);
01518 imout->available->flags = new_line->flags ;
01519 imout->available->back_color = new_line->back_color ;
01520
01521
01522 imout->encode_image_scanline( imout, imout->available );
01523 }
01524 }
01525
01526 void
01527 output_image_line_fast( ASImageOutput *imout, ASScanline *new_line, int ratio )
01528 {
01529
01530 if( new_line )
01531 {
01532 SCANLINE_FUNC_FILTERED(fast_output_filter,*(new_line),*(imout->available),(CARD8)ratio,imout->available->width);
01533 imout->available->flags = new_line->flags ;
01534 imout->available->back_color = new_line->back_color ;
01535 imout->encode_image_scanline( imout, imout->available );
01536 }
01537 }
01538
01539 void
01540 output_image_line_direct( ASImageOutput *imout, ASScanline *new_line, int ratio )
01541 {
01542
01543 if( new_line )
01544 {
01545 if( ratio > 1)
01546 {
01547 SCANLINE_FUNC_FILTERED(divide_component,*(new_line),*(imout->available),(CARD8)ratio,imout->available->width);
01548 imout->available->flags = new_line->flags ;
01549 imout->available->back_color = new_line->back_color ;
01550 imout->encode_image_scanline( imout, imout->available );
01551 }else
01552 imout->encode_image_scanline( imout, new_line );
01553 }
01554 }
01555