imencdec.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2000,2001,2004 Sasha Vasko <sasha at aftercode.net>
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  */
00018 
00019 
00020 /*#undef NO_DEBUG_OUTPUT*/
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 }                             /* vector of doubles */
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  * quality control: we support several levels of quality to allow for
00114  * smooth work on older computers.
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 /* low level routines ****************************************************/
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 /* for consistency sake : */
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;                     /* we are 8byte aligned/padded anyways */
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);  /* psrld */
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" // load 8 bytes from src[i] into MM0
00270                         "psrld $1, %%mm0 \n\t" // MM0=src[i]>>1
00271                         "movq %%mm0, %0  \n\t" // store the result in dest
00272                                         : "=m" (ddst[i]) // %0
00273                                         : "m"  (dsrc[i]) // %1
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 /* ******************** ASImageDecoder ****************************/
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 ;                        /* segfault !!!!! */
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                 /* Bevel should completely encompas output region */
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 /* ******************** ASImageOutput ****************************/
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         {/* choose what kind of error diffusion we'll use : */
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 /* no quanitzation - no error diffusion */
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 /* diffusingly combine src onto self and dst, and rightbitshift src by quantization shift */
00619 static inline void
00620 best_output_filter( register CARD32 *line1, register CARD32 *line2, int unused, int len )
00621 {/* we carry half of the quantization error onto the surrounding pixels : */
00622  /*        X    7/16 */
00623  /* 3/16  5/16  1/16 */
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 {/* we carry half of the quantization error onto the following pixel and store it in dst: */
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 {/*  no error diffusion whatsoever: */
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 {/* we carry half of the quantization error onto the following pixel : */
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 /*                                               DECODER :                                                                */
00747 /* Low level drivers :                                                */
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         {/* need to tile :( */
00842                 ASScanline *xim_scl = imdec->xim_buffer;
00843                 int offset_x = imdec->offset_x%xim_width ;
00844 /*fprintf( stderr, __FILE__ ":" __FUNCTION__ ": width=%d, xim_width=%d, skip = %d, offset_x = %d - tiling\n", width, xim->width, skip, imdec->offset_x );       */
00845 
00846                 GET_SCANLINE(imdec->asv,xim,xim_scl,y,(unsigned char*)xim->data+xim->bytes_per_line*y);
00847                 /* We also need to decode mask if we have one :*/
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         {/* cool we can put data directly into buffer : */
00895 /*fprintf( stderr, __FILE__ ":" __FUNCTION__ ":direct\n" );     */
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                 /* We also need to decode mask if we have one :*/
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 /* High level drivers :                                                */
00937 void                                           /* normal (unbeveled) */
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 /*              fprintf( stderr, __FUNCTION__ " %d: y_out = %d, alt_left = %d, offset_shade = %d, alt_right = %d, scl->width = %d, out_width = %d\n",
01124                                                 __LINE__, y_out, alt_left, offset_shade, alt_right, scl->width, imdec->out_width );
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 /*      fprintf( stderr, __FUNCTION__ " %d: y_out = %d, alt_left = %d, offset_shade = %d, alt_right = %d, scl->width = %d, out_width = %d\n",
01148                                          __LINE__, y_out, alt_left, offset_shade, alt_right, scl->width, imdec->out_width );
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 /* fprintf( stderr, __FUNCTION__ ":%d: y_out = %d, imdec->bevel_top = %d, bevel->top_inline = %d\n",
01206                                 __LINE__,  y_out, imdec->bevel_top, bevel->top_inline);
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 /* fprintf( stderr, __FUNCTION__ ":%d: left_delta = %d, right_delta = %d, left_inline = %d, right_inline = %d, bevel_left = %d, bevel_right = %d\n",
01219                                 __LINE__,  left_delta, right_delta, bevel->left_inline, bevel->right_inline, imdec->bevel_left, imdec->bevel_right);
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 /*                                                ENCODER :                                                               */
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         /*                                              fprintf( stderr, "copy-encoding color %d, from lline %d to %d, %d bytes\n", color, imout->next_line, i, bytes_count );*/
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 /*                                              fprintf( stderr, "copy-encoding color %d, from lline %d to %d, %d bytes\n", color, imout->next_line, i, bytes_count );*/
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         /* caching and preprocessing line into our buffer : */
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         /* copying/encoding previously cahced line into destination image : */
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         /* rotating the buffers : */
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         /* caching and preprocessing line into our buffer : */
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 /*      SCANLINE_MOD(print_component,*(imout->available),0, new_line->width ); */
01521                 /* copying/encoding previously cached line into destination image : */
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         /* caching and preprocessing line into our buffer : */
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         /* caching and preprocessing line into our buffer : */
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 

Generated on Tue Jul 5 14:13:27 2011 for ROOT_528-00b_version by  doxygen 1.5.1