00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #undef LOCAL_DEBUG
00020
00021 #undef DEBUG_ELLIPS
00022
00023 #ifdef _WIN32
00024 #include "win32/config.h"
00025 #else
00026 #include "config.h"
00027 #endif
00028
00029 #ifdef _WIN32
00030 #define Long64_t __int64
00031 #else
00032 #define Long64_t long long
00033 #endif
00034
00035
00036
00037
00038 #include <string.h>
00039 #include <stdlib.h>
00040 #include <ctype.h>
00041 #ifdef _WIN32
00042 # include "win32/afterbase.h"
00043 #else
00044 # include "afterbase.h"
00045 #endif
00046 #include "asvisual.h"
00047 #include "asimage.h"
00048 #include "draw.h"
00049
00050
00051 #define CTX_SELECT_CANVAS(ctx) (get_flags((ctx)->flags, ASDrawCTX_UsingScratch)?(ctx)->scratch_canvas:(ctx)->canvas)
00052
00053 #define CTX_PUT_PIXEL(ctx,x,y,ratio) (ctx)->apply_tool_func(ctx,x,y,ratio)
00054 #define CTX_FILL_HLINE(ctx,x_from,y,x_to,ratio) (ctx)->fill_hline_func(ctx,x_from,y,x_to,ratio)
00055
00056
00057 #define CTX_DEFAULT_FILL_THRESHOLD 126
00058 #define CTX_ELLIPS_FILL_THRESHOLD 140
00059
00060 CARD32 _round1x1[1] =
00061 { 255 };
00062
00063 CARD32 _round3x3[9] =
00064 { 64, 80, 64,
00065 80, 255, 80,
00066 64, 80, 64 };
00067
00068 CARD32 _round3x3_solid[9] =
00069 { 64, 255, 64,
00070 255, 255, 255,
00071 64, 255, 64 };
00072
00073 CARD32 _round5x5[25] =
00074 { 0, 24, 64, 24, 0,
00075 24, 64, 80, 64, 24,
00076 64, 80, 255, 80, 64,
00077 24, 64, 80, 64, 24,
00078 0, 24, 64, 24, 0,};
00079
00080 CARD32 _round5x5_solid[25] =
00081 { 0, 255, 255, 255, 0,
00082 255, 255, 255, 255, 255,
00083 255, 255, 255, 255, 255,
00084 255, 255, 255, 255, 255,
00085 0, 255, 255, 255, 0,};
00086
00087 ASDrawTool StandardBrushes[AS_DRAW_BRUSHES] =
00088 {
00089 {1, 1, 0, 0, _round1x1},
00090 {3, 3, 1, 1, _round3x3_solid},
00091 {5, 5, 2, 2, _round5x5_solid}
00092 };
00093
00094
00095
00096
00097
00098 static void
00099 apply_tool_2D( ASDrawContext *ctx, int curr_x, int curr_y, CARD32 ratio )
00100 {
00101
00102
00103 if( ratio != 0 )
00104 {
00105 CARD32 *src = ctx->tool->matrix ;
00106 int corner_x = curr_x - ctx->tool->center_x ;
00107 int corner_y = curr_y - ctx->tool->center_y ;
00108 int tw = ctx->tool->width ;
00109 int th = ctx->tool->height ;
00110 int cw = ctx->canvas_width ;
00111 int ch = ctx->canvas_height ;
00112 int aw = tw ;
00113 int ah = th ;
00114 CARD32 *dst = CTX_SELECT_CANVAS(ctx) ;
00115 int x, y ;
00116
00117 if( corner_x+tw <= 0 || corner_x >= cw || corner_y+th <= 0 || corner_y >= ch )
00118 return ;
00119
00120 if( corner_y > 0 )
00121 dst += corner_y * cw ;
00122 else if( corner_y < 0 )
00123 {
00124 ah -= -corner_y ;
00125 src += -corner_y * tw ;
00126 }
00127
00128 if( corner_x > 0 )
00129 dst += corner_x ;
00130 else if( corner_x < 0 )
00131 {
00132 src += -corner_x ;
00133 aw -= -corner_x ;
00134 }
00135
00136 if( corner_x + tw > cw )
00137 aw = cw - corner_x;
00138
00139 if( corner_y + th > ch )
00140 ah = ch - corner_y;
00141
00142 if( ratio == 255 )
00143 {
00144 for( y = 0 ; y < ah ; ++y )
00145 {
00146 for( x = 0 ; x < aw ; ++x )
00147 {
00148 if( dst[x] < src[x] )
00149 dst[x] = src[x] ;
00150
00151
00152
00153
00154 }
00155 src += tw ;
00156 dst += cw ;
00157 }
00158 }else
00159 {
00160
00161
00162 CARD32 *tsrc = src-tw;
00163 CARD32 *tdst = dst-cw;
00164
00165 for( y = 0 ; y < ah ; ++y )
00166 {
00167 CARD32 v1, v2;
00168 tsrc += tw ;
00169 tdst += cw ;
00170 v1 = (tsrc[0]*ratio)/255 ;
00171 v2 = (tsrc[aw-1]*ratio)/255 ;
00172 if( tdst[0] < v1 ) tdst[0] = v1 ;
00173 if( tdst[aw-1] < v2 ) tdst[aw-1] = v2 ;
00174 }
00175
00176 for (x = 1 ; x < aw-1 ; ++x)
00177 {
00178 CARD32 v1 = (src[x]*ratio)/255 ;
00179 CARD32 v2 = (tsrc[x]*ratio)/255 ;
00180 if( dst[x] < v1 ) dst[x] = v1 ;
00181 if( tdst[x] < v2 ) tdst[x] = v2 ;
00182 }
00183
00184 for( y = 1 ; y < ah-1 ; ++y )
00185 {
00186 src += tw ;
00187 dst += cw ;
00188 for( x = 1 ; x < aw-1 ; ++x )
00189 if( dst[x] < src[x] )
00190 dst[x] = src[x] ;
00191 }
00192 }
00193 }
00194 }
00195
00196 static inline void alpha_blend_point_argb32( CARD32 *dst, CARD32 value, CARD32 ratio)
00197 {
00198 CARD32 ta = (ARGB32_ALPHA8(value)*ratio)/255;
00199
00200 if (ta >= 255)
00201 *dst = value|0xFF000000;
00202 else
00203 {
00204 CARD32 aa = 255-ta;
00205 CARD32 orig = *dst;
00206 CARD32 res = orig&0xFF000000;
00207 if (res < (ta<<24))
00208 res = (ta<<24);
00209
00210 res |= (((orig&0x00FF00FF)*aa + (value&0x00FF00FF)*ta)>>8)&0x00FF00FF;
00211
00212 res |= (((orig&0x0000FF00)*aa + (value&0x0000FF00)*ta)>>8)&0x0000FF00;
00213 *dst = res;
00214 }
00215 }
00216
00217 static void
00218 apply_tool_2D_colored( ASDrawContext *ctx, int curr_x, int curr_y, CARD32 ratio )
00219 {
00220 if( ratio != 0 )
00221 {
00222 CARD32 *src = ctx->tool->matrix ;
00223 int corner_x = curr_x - ctx->tool->center_x ;
00224 int corner_y = curr_y - ctx->tool->center_y ;
00225 int tw = ctx->tool->width ;
00226 int th = ctx->tool->height ;
00227 int cw = ctx->canvas_width ;
00228 int ch = ctx->canvas_height ;
00229 int aw = tw ;
00230 int ah = th ;
00231 CARD32 *dst = CTX_SELECT_CANVAS(ctx) ;
00232 int x, y ;
00233
00234 if( corner_x+tw <= 0 || corner_x >= cw || corner_y+th <= 0 || corner_y >= ch )
00235 return ;
00236
00237 if( corner_y > 0 )
00238 dst += corner_y * cw ;
00239 else if( corner_y < 0 )
00240 {
00241 ah -= -corner_y ;
00242 src += -corner_y * tw ;
00243 }
00244
00245 if( corner_x > 0 )
00246 dst += corner_x ;
00247 else if( corner_x < 0 )
00248 {
00249 src += -corner_x ;
00250 aw -= -corner_x ;
00251 }
00252
00253 if( corner_x + tw > cw )
00254 aw = cw - corner_x;
00255
00256 if( corner_y + th > ch )
00257 ah = ch - corner_y;
00258
00259
00260
00261 {
00262 CARD32 *tsrc = src-tw;
00263 CARD32 *tdst = dst-cw;
00264
00265 if (get_flags(ctx->flags, ASDrawCTX_UsingScratch))
00266 {
00267 for( y = 0 ; y < ah ; ++y )
00268 {
00269 CARD32 v1, v2;
00270 tsrc += tw ;
00271 tdst += cw ;
00272 v1 = (ARGB32_ALPHA8(tsrc[0])*ratio)/255 ;
00273 v2 = (ARGB32_ALPHA8(tsrc[aw-1])*ratio)/255 ;
00274 if( tdst[0] < v1 ) tdst[0] = v1 ;
00275 if( tdst[aw-1] < v2 ) tdst[aw-1] = v2 ;
00276
00277 }
00278
00279 for (x = 1 ; x < aw-1 ; ++x)
00280 {
00281 CARD32 v1 = (ARGB32_ALPHA8(src[x])*ratio)/255 ;
00282 CARD32 v2 = (ARGB32_ALPHA8(tsrc[x])*ratio)/255 ;
00283 if( dst[x] < v1 ) dst[x] = v1 ;
00284 if( tdst[x] < v2 ) tdst[x] = v2 ;
00285 }
00286
00287 for( y = 1 ; y < ah-1 ; ++y )
00288 {
00289 src += tw ;
00290 dst += cw ;
00291 for( x = 1 ; x < aw-1 ; ++x )
00292 {
00293 CARD32 value = ARGB32_ALPHA8(src[x]);
00294 if( dst[x] < value )
00295 dst[x] = value ;
00296 }
00297 }
00298 }else
00299 {
00300 for( y = 0 ; y < ah ; ++y )
00301 {
00302 tsrc += tw ;
00303 tdst += cw ;
00304 alpha_blend_point_argb32( tdst, tsrc[0], ratio);
00305 alpha_blend_point_argb32( tdst+aw-1, tsrc[aw-1], ratio);
00306 }
00307 for (x = 1 ; x < aw-1 ; ++x)
00308 {
00309 alpha_blend_point_argb32( dst+x, src[x], ratio);
00310 alpha_blend_point_argb32( tdst+x, tsrc[x], ratio);
00311 }
00312
00313 for( y = 1 ; y < ah-1 ; ++y )
00314 {
00315 src += tw ;
00316 dst += cw ;
00317 for( x = 1 ; x < aw-1 ; ++x )
00318 alpha_blend_point_argb32( dst+x, src[x], 255);
00319 }
00320 }
00321 }
00322 }
00323 }
00324
00325
00326 static void
00327 apply_tool_point( ASDrawContext *ctx, int curr_x, int curr_y, CARD32 ratio )
00328 {
00329 int cw = ctx->canvas_width ;
00330 if( ratio != 0 && curr_x >= 0 && curr_x < cw && curr_y >= 0 && curr_y < ctx->canvas_height )
00331 {
00332 CARD32 value = (ctx->tool->matrix[0]*ratio)/255 ;
00333 CARD32 *dst = CTX_SELECT_CANVAS(ctx) ;
00334 dst += curr_y * cw ;
00335
00336 if( dst[curr_x] < value )
00337 dst[curr_x] = value ;
00338 }
00339 }
00340
00341
00342 static void
00343 apply_tool_point_colored(ASDrawContext *ctx, int curr_x, int curr_y, CARD32 ratio)
00344 {
00345
00346 int cw = ctx->canvas_width;
00347 if (curr_x >= 0 && curr_x < cw && curr_y >= 0 && curr_y < ctx->canvas_height && ratio != 0)
00348 {
00349 CARD32 *dst = CTX_SELECT_CANVAS(ctx);
00350 dst += curr_y * cw + curr_x;
00351 if (get_flags(ctx->flags, ASDrawCTX_UsingScratch))
00352 {
00353 CARD32 value = (ARGB32_ALPHA8(ctx->tool->matrix[0])*ratio)/255 ;
00354 if( *dst < value )
00355 *dst = value ;
00356 }
00357 else
00358 alpha_blend_point_argb32( dst, ctx->tool->matrix[0], ratio);
00359
00360 }
00361 }
00362
00363 static void
00364 fill_hline_notile( ASDrawContext *ctx, int x_from, int y, int x_to, CARD32 ratio )
00365 {
00366 int cw = ctx->canvas_width ;
00367 if( ratio != 0 && x_to >= 0 && x_from < cw && y >= 0 && y < ctx->canvas_height )
00368 {
00369 CARD32 value = ratio ;
00370 CARD32 *dst = CTX_SELECT_CANVAS(ctx) + y * cw ;
00371 int x1 = x_from, x2 = x_to ;
00372 if( x1 < 0 )
00373 x1 = 0 ;
00374 if( x2 >= cw )
00375 x2 = cw - 1 ;
00376
00377 while( x1 <= x2 )
00378 {
00379 if( dst[x1] < value )
00380 dst[x1] = value ;
00381 ++x1 ;
00382 }
00383 }
00384 }
00385
00386 static void
00387 fill_hline_notile_colored(ASDrawContext *ctx, int x_from, int y, int x_to, CARD32 ratio)
00388 {
00389 int cw = ctx->canvas_width ;
00390 if( ratio != 0 && x_to >= 0 && x_from < cw && y >= 0 && y < ctx->canvas_height )
00391 {
00392 CARD32 value = ctx->tool->matrix[0] ;
00393 CARD32 *dst = CTX_SELECT_CANVAS(ctx) + y * cw ;
00394 int x1 = x_from, x2 = x_to ;
00395 if( x1 < 0 )
00396 x1 = 0 ;
00397 if( x2 >= cw )
00398 x2 = cw - 1 ;
00399
00400 if (get_flags(ctx->flags, ASDrawCTX_UsingScratch))
00401 {
00402 while( x1 <= x2 )
00403 {
00404 CARD32 value = (ARGB32_ALPHA8(ctx->tool->matrix[0])*ratio)/255 ;
00405 if( dst[x1] < value )
00406 dst[x1] = value ;
00407 ++x1 ;
00408 }
00409 }else
00410 while( x1 <= x2 )
00411 {
00412 alpha_blend_point_argb32( dst+x1, value, ratio);
00413 ++x1 ;
00414 }
00415 }
00416 }
00417
00418
00419
00420
00421 static void
00422 ctx_draw_line_solid( ASDrawContext *ctx, int from_x, int from_y, int to_x, int to_y )
00423 {
00424 int x, y, end, dir = 1;
00425 int dx = to_x - from_x ;
00426 int dy = to_y - from_y ;
00427 if( dx < 0 )
00428 dx = -dx ;
00429 if( dy < 0 )
00430 dy = -dy ;
00431
00432 if( dx >= dy )
00433 {
00434 int Dy = -dx + 2*dy;
00435 int inct = 2*dy;
00436 int incf = 2*(dy - dx);
00437
00438 if( to_y > from_y )
00439 { x = from_x ; y = from_y ; end = to_x ; }
00440 else
00441 { x = to_x ; y = to_y ; end = from_x ; }
00442
00443 if( end < x )
00444 dir = -1 ;
00445
00446 CTX_PUT_PIXEL( ctx, x, y, 255 );
00447 while(x != end)
00448 {
00449 x += dir;
00450 if(Dy > 0)
00451 {
00452 Dy += incf;
00453 ++y;
00454 }else
00455 Dy += inct;
00456 CTX_PUT_PIXEL( ctx, x, y, 255 );
00457 }
00458 }else
00459 {
00460 int Dx = -dy + 2*dx;
00461 int inct = 2*dx;
00462 int incf = 2*(dx - dy);
00463
00464 if( to_x > from_x )
00465 { y = from_y ; x = from_x ; end = to_y ; }
00466 else
00467 { y = to_y ; x = to_x ; end = from_y ; }
00468
00469 if( end < y )
00470 dir = -1 ;
00471
00472 CTX_PUT_PIXEL( ctx, x, y, 255 );
00473 while(y != end)
00474 {
00475 y += dir;
00476 if(Dx > 0)
00477 {
00478 Dx += incf;
00479 ++x;
00480 }else
00481 Dx += inct;
00482 CTX_PUT_PIXEL( ctx, x, y, 255 );
00483 }
00484 }
00485 }
00486
00487 static void
00488 ctx_draw_line_solid_aa( ASDrawContext *ctx, int from_x, int from_y, int to_x, int to_y )
00489 {
00490 #define RATIO_t int
00491 int x, y, end, dir = 1;
00492 int dx = to_x - from_x ;
00493 int dy = to_y - from_y ;
00494 if( dx < 0 )
00495 dx = -dx ;
00496 if( dy < 0 )
00497 dy = -dy ;
00498
00499 if( dx == 0 || dy == 0 )
00500 {
00501 ctx_draw_line_solid( ctx, from_x, from_y, to_x, to_y );
00502 return ;
00503 }
00504
00505 if( dx >= dy )
00506 {
00507 RATIO_t ratio2 = 0x007FFFFF/dx ;
00508 CARD32 value = 0x003FFFFF;
00509 CARD32 value_incr = ratio2*dy ;
00510 int value_decr = (dx - dy)*ratio2 ;
00511
00512
00513 if( to_y > from_y )
00514 { x = from_x ; y = from_y ; end = to_x ; }
00515 else
00516 { x = to_x ; y = to_y ; end = from_x ; }
00517
00518 if( end < x ) dir = -1 ;
00519
00520 CTX_PUT_PIXEL( ctx, x, y, 255 );
00521
00522
00523
00524 while(x != end)
00525 {
00526 x += dir;
00527 if( (int)value > value_decr)
00528 {
00529 value = (int)value - value_decr ;
00530 ++y;
00531 }else
00532 value += value_incr ;
00533
00534 {
00535 RATIO_t above = (value&0x00FF0000)>>16;
00536
00537 switch( (above>>5)&0x03 )
00538 {
00539 case 0 :
00540 above = 128 - above ;
00541 CTX_PUT_PIXEL( ctx, x, y-1, above ) ;
00542 CTX_PUT_PIXEL( ctx, x, y, (~(above>>1))&0x00FF ) ;
00543 break ;
00544 case 1 :
00545 {
00546 RATIO_t a1 = (above - 32) ;
00547 CTX_PUT_PIXEL( ctx, x, y+1, a1 ) ;
00548 above = (~above)&0x7f ;
00549 CTX_PUT_PIXEL( ctx, x, y-1, above - a1 ) ;
00550 CTX_PUT_PIXEL( ctx, x, y, 255 ) ;
00551 }
00552 break ;
00553 case 2 :
00554 {
00555 RATIO_t a1 = (96 - above) ;
00556 CTX_PUT_PIXEL( ctx, x, y-1, a1 ) ;
00557 CTX_PUT_PIXEL( ctx, x, y, 255 ) ;
00558 CTX_PUT_PIXEL( ctx, x, y+1, above - a1 ) ;
00559 }
00560 break ;
00561 case 3 :
00562 {
00563 above -= ((~above)&0x7f)>>1 ;
00564 CTX_PUT_PIXEL( ctx, x, y, (~(above>>1))&0x00FF ) ;
00565 CTX_PUT_PIXEL( ctx, x, y+1, above ) ;
00566 }
00567 break ;
00568 }
00569 }
00570 }
00571 }else
00572 {
00573 RATIO_t ratio2 = 0x007FFFFF/dy ;
00574 CARD32 value = 0x003FFFFF;
00575 CARD32 value_incr = ratio2*dx ;
00576 int value_decr = (dy - dx)*ratio2 ;
00577
00578
00579 if( to_x > from_x )
00580 { y = from_y ; x = from_x ; end = to_y ; }
00581 else
00582 { y = to_y ; x = to_x ; end = from_y ; }
00583
00584 if( end < y ) dir = -1 ;
00585
00586 CTX_PUT_PIXEL( ctx, x, y, 255 );
00587
00588
00589
00590 while(y != end)
00591 {
00592 y += dir;
00593 if( (int)value > value_decr)
00594 {
00595 value = (int)value - value_decr ;
00596 ++x;
00597 }else
00598 value += value_incr ;
00599
00600 {
00601 RATIO_t above = (value&0x00FF0000)>>16;
00602
00603 switch( (above>>5)&0x03 )
00604 {
00605 case 0 :
00606 above = 128 - above ;
00607 CTX_PUT_PIXEL( ctx, x-1, y, above ) ;
00608 CTX_PUT_PIXEL( ctx, x, y, (~(above>>1))&0x00FF ) ;
00609 break ;
00610 case 1 :
00611 {
00612 RATIO_t a1 = (above - 32) ;
00613 CTX_PUT_PIXEL( ctx, x+1, y, a1 ) ;
00614 above = (~above)&0x7f ;
00615 CTX_PUT_PIXEL( ctx, x-1, y, above - a1 ) ;
00616 CTX_PUT_PIXEL( ctx, x, y, 255 ) ;
00617 }
00618 break ;
00619 case 2 :
00620 {
00621 RATIO_t a1 = (96 - above) ;
00622 CTX_PUT_PIXEL( ctx, x-1, y, a1 ) ;
00623 CTX_PUT_PIXEL( ctx, x, y, 255 ) ;
00624 CTX_PUT_PIXEL( ctx, x+1, y, above - a1 ) ;
00625 }
00626 break ;
00627 case 3 :
00628 {
00629 above -= ((~above)&0x7f)>>1 ;
00630 CTX_PUT_PIXEL( ctx, x, y, (~(above>>1))&0x00FF ) ;
00631 CTX_PUT_PIXEL( ctx, x+1, y, above ) ;
00632 }
00633 break ;
00634 }
00635 }
00636 }
00637 }
00638 }
00639
00640 #define SUPERSAMPLING_BITS 8
00641 #define SUPERSAMPLING_MASK 0x000000FF
00642
00643 static inline void
00644 render_supersampled_pixel( ASDrawContext *ctx, int xs, int ys )
00645 {
00646 if( xs >= 0 && ys >= 0 )
00647 {
00648 unsigned int xe = xs&SUPERSAMPLING_MASK ;
00649 unsigned int nxe = (~xs)&SUPERSAMPLING_MASK ;
00650 unsigned int x = xs>>SUPERSAMPLING_BITS;
00651 unsigned int ye = ys&SUPERSAMPLING_MASK ;
00652 unsigned int nye = (~ys)&SUPERSAMPLING_MASK ;
00653 unsigned int y = ys>>SUPERSAMPLING_BITS;
00654 unsigned int v = (nxe*nye)>>8 ;
00655
00656 CTX_PUT_PIXEL( ctx, x, y, v ) ;
00657
00658 v = (xe*(nye))>>8 ;
00659 CTX_PUT_PIXEL( ctx, x+1, y, v ) ;
00660 v = ((nxe)*ye)>>8 ;
00661 CTX_PUT_PIXEL( ctx, x, ++y, v ) ;
00662 v = (xe*ye)>>8 ;
00663 CTX_PUT_PIXEL( ctx, x+1, y, v ) ;
00664 }
00665 }
00666
00667 typedef struct ASCubicBezier
00668 {
00669 int x0, y0;
00670 int x1, y1;
00671 int x2, y2;
00672 int x3, y3;
00673 }ASCubicBezier;
00674
00675 static void
00676 ctx_draw_bezier( ASDrawContext *ctx, int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3 )
00677 {
00678 int ch = ctx->canvas_height<<8 ;
00679 int cw = ctx->canvas_width<<8 ;
00680
00681 ASCubicBezier *bstack = NULL ;
00682 int bstack_size = 0, bstack_used = 0 ;
00683
00684 #define ADD_CubicBezier(X0,Y0,X1,Y1,X2,Y2,X3,Y3) \
00685 do{ \
00686 if( ((X0)>=0 || (X1)>=0 || (X2)>=0 || (X3)>=0) && ((X0)<cw||(X1)<cw||(X2)<cw||(X3)<cw) && \
00687 ((Y0)>=0 || (Y1)>=0 || (Y2)>=0 || (Y3)>=0) && ((Y0)<ch||(Y1)<ch||(Y2)<ch||(Y3)<ch) ){ \
00688 while( bstack_used >= bstack_size ) { \
00689 bstack_size += 2048/sizeof(ASCubicBezier); \
00690 bstack = (ASCubicBezier *)realloc( bstack, bstack_size*sizeof(ASCubicBezier)); \
00691 } \
00692 LOCAL_DEBUG_OUT( "(%d,%d),(%d,%d),(%d,%d),(%d,%d)", X0, Y0, X1, Y1, X2, Y2, X3, Y3 ); \
00693 bstack[bstack_used].x0=X0; \
00694 bstack[bstack_used].y0=Y0; \
00695 bstack[bstack_used].x1=X1; \
00696 bstack[bstack_used].y1=Y1; \
00697 bstack[bstack_used].x2=X2; \
00698 bstack[bstack_used].y2=Y2; \
00699 bstack[bstack_used].x3=X3; \
00700 bstack[bstack_used].y3=Y3; \
00701 ++bstack_used ; \
00702 } \
00703 }while(0)
00704
00705
00706 ADD_CubicBezier(x0,y0,x1,y1,x2,y2,x3,y3);
00707
00708 while( bstack_used > 0 )
00709 {
00710 --bstack_used ;
00711 x0 = bstack[bstack_used].x0 ;
00712 y0 = bstack[bstack_used].y0 ;
00713 x1 = bstack[bstack_used].x1 ;
00714 y1 = bstack[bstack_used].y1 ;
00715 x2 = bstack[bstack_used].x2 ;
00716 y2 = bstack[bstack_used].y2 ;
00717 x3 = bstack[bstack_used].x3 ;
00718 y3 = bstack[bstack_used].y3 ;
00719 {
00720 int x01 = x0 + ((x1-x0)>>1) ;
00721 int y01 = y0 + ((y1-y0)>>1) ;
00722 int x11 = x1 + ((x2-x1)>>1) ;
00723 int y11 = y1 + ((y2-y1)>>1) ;
00724 int x31 = x3 + ((x2-x3)>>1) ;
00725 int y31 = y3 + ((y2-y3)>>1) ;
00726
00727 int x011 = x01 + ((x11-x01)>>1) ;
00728 int y011 = y01 + ((y11-y01)>>1) ;
00729 int x111 = x11 + ((x31-x11)>>1) ;
00730 int y111 = y11 + ((y31-y11)>>1) ;
00731
00732 int x0111 = x011 + ((x111-x011)>>1) ;
00733 int y0111 = y011 + ((y111-y011)>>1) ;
00734
00735 if( (x0&0xFFFFFF00) == (x0111&0xFFFFFF00) && (y0&0xFFFFFF00) == (y0111&0xFFFFFF00) )
00736 {
00737 render_supersampled_pixel( ctx, x0, y0 );
00738 }else if( x01 != x1 || y01 != y1 || x011 != x2 || y011 != y2 || x0111 != x3 || y0111 != y3 )
00739 ADD_CubicBezier( x0, y0, x01, y01, x011, y011, x0111, y0111 );
00740
00741 if( (x3&0xFFFFFF00) == (x0111&0xFFFFFF00) && (y3&0xFFFFFF00) == (y0111&0xFFFFFF00) )
00742 {
00743 render_supersampled_pixel( ctx, x3, y3 );
00744 }else if( x0111 != x0 || y0111 != y0 || x111 != x1 || y111 != y1 || x31 != x2 || y31 != y2 )
00745 ADD_CubicBezier( x0111, y0111, x111, y111, x31, y31, x3, y3 );
00746 }
00747 }
00748 if( bstack )
00749 free( bstack );
00750 }
00751
00752 typedef struct ASScanlinePart
00753 {
00754 int y ;
00755 int x0, x1;
00756 }ASScanlinePart;
00757
00758
00759 static void
00760 ctx_flood_fill( ASDrawContext *ctx, int x_from, int y, int x_to, CARD32 min_val, CARD32 max_val )
00761 {
00762 int ch = ctx->canvas_height ;
00763 int cw = ctx->canvas_width ;
00764
00765 ASScanlinePart *sstack = NULL ;
00766 int sstack_size = 0, sstack_used = 0 ;
00767 CARD32 *canvas = CTX_SELECT_CANVAS(ctx);
00768
00769 LOCAL_DEBUG_OUT( "(%d,%d,%d)", x_from, y, x_to );
00770 #define ADD_ScanlinePart(X0,Y0,X1) \
00771 do{ \
00772 if( ((X0)>=0 || (X1)>=0 ) && ((X0)<cw||(X1)<cw) && \
00773 (Y0)>=0 && (Y0)<ch ){ \
00774 while( sstack_used >= sstack_size ) { \
00775 sstack_size += 2048/sizeof(ASScanlinePart); \
00776 sstack = realloc( sstack, sstack_size*sizeof(ASScanlinePart)); \
00777 } \
00778 LOCAL_DEBUG_OUT( "(%d,%d,%d)", X0, Y0, X1 ); \
00779 sstack[sstack_used].x0=X0; \
00780 sstack[sstack_used].y=Y0; \
00781 sstack[sstack_used].x1=X1; \
00782 ++sstack_used ; \
00783 } \
00784 }while(0)
00785
00786 ADD_ScanlinePart(x_from,y,x_to);
00787
00788 while( sstack_used > 0 )
00789 {
00790 --sstack_used ;
00791 x_from = sstack[sstack_used].x0 ;
00792 x_to = sstack[sstack_used].x1 ;
00793 y = sstack[sstack_used].y ;
00794 if( x_from < 0 )
00795 x_from = 0 ;
00796 if( x_to >= cw )
00797 x_to = cw - 1 ;
00798 if( x_from <= x_to )
00799 {
00800
00801 if( y > 0 )
00802 {
00803 CARD32 *data = canvas + (y-1)*cw ;
00804 int xc = x_from ;
00805
00806 while( xc <= x_to )
00807 {
00808 if( data[xc] <= max_val && data[xc] >= min_val )
00809 {
00810 int x0 = xc, x1 = xc ;
00811 while( x0 >= 0 && data[x0] <= max_val && data[x0] >= min_val ) --x0;
00812 ++x0 ;
00813 while( x1 < cw && data[x1] <= max_val && data[x1] >= min_val ) ++x1;
00814 --x1 ;
00815
00816 ADD_ScanlinePart(x0,y-1,x1);
00817 LOCAL_DEBUG_OUT( "x = %d, y = %d, data[x] = 0x%X, x0 = %d, x1 = %d", xc, y-1, data[xc], x0, x1 );
00818 while( xc <= x_to && xc <= x1+1 ) ++xc ;
00819 }else
00820 ++xc ;
00821 }
00822 }
00823 if( y < ch-1 )
00824 {
00825 CARD32 *data = canvas + (y+1)*cw ;
00826 int xc = x_from ;
00827
00828 while( xc <= x_to )
00829 {
00830 if( data[xc] <= max_val && data[xc] >= min_val )
00831 {
00832 int x0 = xc, x1 = xc ;
00833 while( x0 >= 0 && data[x0] <= max_val && data[x0] >= min_val ) --x0;
00834 ++x0 ;
00835 while( x1 < cw && data[x1] <= max_val && data[x1] >= min_val ) ++x1;
00836 --x1 ;
00837 LOCAL_DEBUG_OUT( "x = %d, y = %d, data[x] = 0x%X, x0 = %d, x1 = %d", xc, y+1, data[xc], x0, x1 );
00838 ADD_ScanlinePart(x0,y+1,x1);
00839 while( xc <= x_to && xc <= x1+1 ) ++xc ;
00840 }else
00841 ++xc ;
00842 }
00843 }
00844 CTX_FILL_HLINE(ctx,x_from,y,x_to,255);
00845 }
00846 }
00847 if( sstack )
00848 free( sstack );
00849
00850
00851 }
00852
00853
00854
00855
00856 Bool
00857 clip_line( int k, int x0, int y0, int cw, int ch, int *x, int*y )
00858 {
00859 int new_x = *x ;
00860 int new_y = *y ;
00861
00862 if( new_x < 0 )
00863 {
00864 new_x = 0 ;
00865 new_y = (-x0 / k) + y0 ;
00866 }
00867 if( new_y < 0 )
00868 {
00869 new_y = 0 ;
00870 new_x = -y0 * k + x0 ;
00871 }
00872 if( new_x < 0 )
00873 return False;
00874
00875
00876 if( new_x >= cw )
00877 {
00878 new_x = cw - 1 ;
00879 if( k != 0 )
00880 {
00881 new_y = (new_x - x0)/k + y0 ;
00882 if( new_y < 0 )
00883 return False;
00884 }
00885 }
00886 if( new_y >= ch )
00887 {
00888 new_y = ch - 1 ;
00889 new_x = (new_y - y0) * k + x0 ;
00890 if( new_x < 0 || new_x >= cw )
00891 return False;
00892 }
00893 *x = new_x ;
00894 *y = new_y ;
00895 return True;
00896 }
00897
00898
00899
00900
00901 Bool asim_set_brush( ASDrawContext *ctx, int brush );
00902
00903 ASDrawContext *
00904 create_asdraw_context( unsigned int width, unsigned int height )
00905 {
00906 ASDrawContext *ctx = safecalloc( 1, sizeof(ASDrawContext));
00907
00908 ctx->canvas_width = width == 0 ? 1 : width ;
00909 ctx->canvas_height = height == 0 ? 1 : height ;
00910 ctx->canvas = safecalloc( ctx->canvas_width*ctx->canvas_height, sizeof(CARD32));
00911
00912 asim_set_brush( ctx, 0 );
00913 ctx->fill_hline_func = fill_hline_notile ;
00914
00915 return ctx;
00916 }
00917
00918 void
00919 destroy_asdraw_context( ASDrawContext *ctx )
00920 {
00921 if( ctx )
00922 {
00923 if( ctx->canvas )
00924 free( ctx->canvas );
00925 if( ctx->scratch_canvas )
00926 free( ctx->scratch_canvas );
00927 free( ctx );
00928 }
00929 }
00930
00931 Bool
00932 asim_set_brush( ASDrawContext *ctx, int brush )
00933 {
00934 if( brush >= 0 && brush < AS_DRAW_BRUSHES && ctx != NULL )
00935 {
00936 ctx->tool = &(StandardBrushes[brush]) ;
00937 if( ctx->tool->width == 1 && ctx->tool->height == 1 )
00938 ctx->apply_tool_func = apply_tool_point ;
00939 else
00940 ctx->apply_tool_func = apply_tool_2D ;
00941
00942 ctx->fill_hline_func = fill_hline_notile ;
00943
00944 clear_flags (ctx->flags, ASDrawCTX_ToolIsARGB);
00945
00946 return True;
00947 }
00948 return False;
00949 }
00950
00951 Bool
00952 asim_set_custom_brush( ASDrawContext *ctx, ASDrawTool *brush)
00953 {
00954 if( brush !=NULL && ctx != NULL )
00955 {
00956 ctx->tool = brush ;
00957 if( ctx->tool->width == 1 && ctx->tool->height == 1 )
00958 ctx->apply_tool_func = apply_tool_point ;
00959 else
00960 ctx->apply_tool_func = apply_tool_2D ;
00961
00962 ctx->fill_hline_func = fill_hline_notile ;
00963
00964 clear_flags (ctx->flags, ASDrawCTX_ToolIsARGB);
00965
00966 return True;
00967 }
00968 return False;
00969 }
00970
00971 Bool
00972 asim_set_custom_brush_colored( ASDrawContext *ctx, ASDrawTool *brush)
00973 {
00974 if( brush !=NULL && ctx != NULL )
00975 {
00976 ctx->tool = brush ;
00977 if( ctx->tool->width == 1 && ctx->tool->height == 1 )
00978 ctx->apply_tool_func = apply_tool_point_colored ;
00979 else
00980 ctx->apply_tool_func = apply_tool_2D_colored ;
00981
00982 ctx->fill_hline_func = fill_hline_notile_colored ;
00983 set_flags (ctx->flags, ASDrawCTX_ToolIsARGB);
00984
00985 return True;
00986 }
00987 return False;
00988 }
00989
00990
00991 Bool
00992 asim_start_path( ASDrawContext *ctx )
00993 {
00994 if( ctx == NULL )
00995 return False;
00996 LOCAL_DEBUG_OUT( "scratch_canvas = %p, flags = 0x%lx", ctx->scratch_canvas, ctx->flags );
00997 if( ctx->scratch_canvas )
00998 {
00999 if( get_flags( ctx->flags, ASDrawCTX_UsingScratch ) )
01000 return False;
01001 memset( ctx->scratch_canvas, 0x00, ctx->canvas_width*ctx->canvas_height*sizeof(CARD32) );
01002 }else
01003 ctx->scratch_canvas = safecalloc( ctx->canvas_width*ctx->canvas_height, sizeof(CARD32));
01004 set_flags( ctx->flags, ASDrawCTX_UsingScratch );
01005 return True;
01006 }
01007
01008 void asim_flood_fill( ASDrawContext *ctx, int x, int y, CARD32 min_val, CARD32 max_val );
01009
01010
01011 Bool
01012 asim_apply_path( ASDrawContext *ctx, int start_x, int start_y, Bool fill, int fill_start_x, int fill_start_y, CARD8 fill_threshold )
01013 {
01014 if( ctx == NULL || !get_flags( ctx->flags, ASDrawCTX_UsingScratch ))
01015 return False;
01016
01017 LOCAL_DEBUG_CALLER_OUT( "start_x = %d, start_y = %d, fill = %d, fill_start_x = %d, fill_start_y = %d",
01018 start_x, start_y, fill, fill_start_x, fill_start_y );
01019
01020
01021 if( fill )
01022 asim_flood_fill( ctx, fill_start_x, fill_start_y, 0, fill_threshold==0?CTX_DEFAULT_FILL_THRESHOLD:fill_threshold );
01023
01024 clear_flags( ctx->flags, ASDrawCTX_UsingScratch );
01025
01026
01027 {
01028 int i = ctx->canvas_width*ctx->canvas_height ;
01029 if (get_flags (ctx->flags, ASDrawCTX_CanvasIsARGB))
01030 {
01031 CARD32 argb = ctx->tool->matrix[ctx->tool->center_y*ctx->tool->width + ctx->tool->center_x];
01032 while (--i >= 0)
01033 if (ctx->scratch_canvas[i])
01034 alpha_blend_point_argb32( ctx->canvas + i, argb, ctx->scratch_canvas[i]);
01035 }else
01036 {
01037 while( --i >= 0 )
01038 if( ctx->canvas[i] < ctx->scratch_canvas[i] )
01039 ctx->canvas[i] = ctx->scratch_canvas[i] ;
01040 }
01041 }
01042 return True;
01043 }
01044
01045 Bool
01046 apply_asdraw_context( ASImage *im, ASDrawContext *ctx, ASFlagType filter )
01047 {
01048 int chan ;
01049 int width, height ;
01050 if( im == NULL || ctx == NULL || filter == 0 )
01051 return False;
01052
01053 width = im->width ;
01054 height = im->height ;
01055 if( width != ctx->canvas_width || height != ctx->canvas_height )
01056 return False;
01057
01058 for( chan = 0 ; chan < IC_NUM_CHANNELS; chan++ )
01059 if( get_flags( filter, 0x01<<chan) )
01060 {
01061 int y;
01062 register ASStorageID *rows = im->channels[chan] ;
01063 register CARD32 *canvas_row = ctx->canvas ;
01064 for( y = 0 ; y < height ; ++y )
01065 {
01066 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPUT)
01067 {
01068 int i;
01069 fprintf( stderr, "row %d, canvas_row = %p:", y, canvas_row );
01070 for( i = 0 ; i < width ; ++i)
01071 fprintf( stderr, "0x%8.8lX ", canvas_row[i] );
01072 fprintf( stderr, "\n" );
01073 }
01074 #endif
01075 if( rows[y] )
01076 forget_data( NULL, rows[y] );
01077 rows[y] = store_data( NULL, (CARD8*)canvas_row, width*sizeof(CARD32), ASStorage_32Bit|ASStorage_RLEDiffCompress, 0);
01078 canvas_row += width ;
01079 }
01080 }
01081 return True;
01082 }
01083
01084
01085
01086
01087
01088
01089 void asim_move_to( ASDrawContext *ctx, int dst_x, int dst_y );
01090
01091 void
01092 asim_line_to_generic( ASDrawContext *ctx, int dst_x, int dst_y, void (*func)(ASDrawContext*,int,int,int,int))
01093 {
01094 if( ctx )
01095 {
01096 int from_x = ctx->curr_x ;
01097 int from_y = ctx->curr_y ;
01098 int to_x = dst_x ;
01099 int to_y = dst_y ;
01100 int cw = ctx->canvas_width ;
01101 int ch = ctx->canvas_height ;
01102
01103 asim_move_to( ctx, dst_x, dst_y );
01104
01105 if( to_y == from_y )
01106 {
01107 if( to_y < 0 || to_y >= ch )
01108 return ;
01109 if( from_x < 0 )
01110 from_x = 0 ;
01111 else if( from_x >= cw )
01112 from_x = cw - 1 ;
01113 if( to_x < 0 )
01114 to_x = 0 ;
01115 else if( to_x >= cw )
01116 to_x = cw - 1 ;
01117 }else if( to_x == from_x )
01118 {
01119 if( to_x < 0 || to_x >= ch )
01120 return ;
01121 if( from_y < 0 )
01122 from_y = 0 ;
01123 else if( from_y >= ch )
01124 from_y = ch - 1 ;
01125 if( to_y < 0 )
01126 to_y = 0 ;
01127 else if( to_y >= ch )
01128 to_y = ch - 1 ;
01129 }else
01130 {
01131 int k = (to_x - from_x)/(to_y - from_y);
01132 int x0 = from_x ;
01133 int y0 = from_y ;
01134
01135 if( (from_x < 0 && to_x < 0 ) || (from_y < 0 && to_y < 0 ) ||
01136 (from_x >= cw && to_x >= cw ) || (from_y >= ch && to_y >= ch ))
01137 return ;
01138
01139 if( !clip_line( k, x0, y0, cw, ch, &from_x, &from_y ) )
01140 return ;
01141 if( !clip_line( k, x0, y0, cw, ch, &to_x, &to_y ) )
01142 return ;
01143 }
01144 if( from_x != to_x || from_y != to_y )
01145 func( ctx, from_x, from_y, to_x, to_y );
01146 }
01147 }
01148
01149
01150
01151
01152 void
01153 asim_move_to( ASDrawContext *ctx, int dst_x, int dst_y )
01154 {
01155 if( ctx )
01156 {
01157 ctx->curr_x = dst_x ;
01158 ctx->curr_y = dst_y ;
01159 }
01160 }
01161
01162 void
01163 asim_line_to( ASDrawContext *ctx, int dst_x, int dst_y )
01164 {
01165 asim_line_to_generic( ctx, dst_x, dst_y, ctx_draw_line_solid);
01166 }
01167
01168
01169 void
01170 asim_line_to_aa( ASDrawContext *ctx, int dst_x, int dst_y )
01171 {
01172 asim_line_to_generic( ctx, dst_x, dst_y, ctx_draw_line_solid_aa);
01173 }
01174
01175 void
01176 asim_cube_bezier( ASDrawContext *ctx, int x1, int y1, int x2, int y2, int x3, int y3 )
01177 {
01178 if( ctx )
01179 {
01180 int x0 = ctx->curr_x;
01181 int y0 = ctx->curr_y;
01182 Bool path_started = False;
01183
01184 if (get_flags (ctx->flags, ASDrawCTX_CanvasIsARGB))
01185 path_started = asim_start_path (ctx);
01186
01187 asim_move_to( ctx, x3, y3 );
01188 ctx_draw_bezier( ctx, x0<<8, y0<<8, x1<<8, y1<<8, x2<<8, y2<<8, x3<<8, y3<<8 );
01189
01190 if (path_started)
01191 asim_apply_path( ctx, 0, 0, False, 0, 0, 0);
01192 }
01193 }
01194
01195
01196
01197
01198
01199 const signed int ASIM_SIN[91]=
01200 {
01201 0x00000000,
01202 0x00000478,0x000008EF,0x00000D66,0x000011DC,0x00001650,0x00001AC2,0x00001F33,0x000023A1,0x0000280C,0x00002C74,
01203 0x000030D9,0x0000353A,0x00003996,0x00003DEF,0x00004242,0x00004690,0x00004AD9,0x00004F1C,0x00005358,0x0000578F,
01204 0x00005BBE,0x00005FE6,0x00006407,0x00006820,0x00006C31,0x00007039,0x00007439,0x0000782F,0x00007C1C,0x00008000,
01205
01206 0x000083DA,0x000087A9,0x00008B6D,0x00008F27,0x000092D6,0x00009679,0x00009A11,0x00009D9C,0x0000A11B,0x0000A48E,
01207 0x0000A7F3,0x0000AB4C,0x0000AE97,0x0000B1D5,0x0000B505,0x0000B827,0x0000BB3A,0x0000BE3F,0x0000C135,0x0000C41B,
01208 0x0000C6F3,0x0000C9BB,0x0000CC73,0x0000CF1C,0x0000D1B4,0x0000D43C,0x0000D6B3,0x0000D91A,0x0000DB6F,0x0000DDB4,
01209 0x0000DFE7,0x0000E209,0x0000E419,0x0000E617,0x0000E804,0x0000E9DE,0x0000EBA6,0x0000ED5C,0x0000EEFF,0x0000F090,
01210 0x0000F20E,0x0000F378,0x0000F4D0,0x0000F615,0x0000F747,0x0000F865,0x0000F970,0x0000FA68,0x0000FB4C,0x0000FC1C,
01211 0x0000FCD9,0x0000FD82,0x0000FE18,0x0000FE99,0x0000FF07,0x0000FF60,0x0000FFA6,0x0000FFD8,0x0000FFF6,0x00010000
01212 };
01213
01214 static inline int asim_sin( int angle )
01215 {
01216 while( angle >= 360 )
01217 angle -= 360 ;
01218 while( angle < 0 )
01219 angle += 360 ;
01220 if( angle <= 90 )
01221 return ASIM_SIN[angle];
01222 if( angle <= 180 )
01223 return ASIM_SIN[180-angle];
01224 if( angle <= 270 )
01225 return -ASIM_SIN[angle-180];
01226 return -ASIM_SIN[360-angle];
01227 }
01228
01229 int
01230 asim_sqrt( double sval )
01231 {
01232 #ifdef HAVE_LONG_LONG
01233 Long64_t uval = (sval >= 0) ? (Long64_t)sval:-(Long64_t)sval ;
01234 Long64_t res = uval ;
01235 Long64_t t = res*res ;
01236 #else
01237 long uval = (sval >= 0) ? (long)sval:-(long)sval ;
01238 long res = uval ;
01239 long t = res*res ;
01240 #endif
01241
01242 while( t > uval )
01243 {
01244 res = res >> 1 ;
01245 t = t >> 2 ;
01246 }
01247 if( t == uval )
01248 return (int)res;
01249 res = (res << 1) + 1 ;
01250 t = res*res ;
01251 while( t > uval )
01252 {
01253 t -= (res<<1)-1 ;
01254 --res ;
01255 }
01256 return (int)res;
01257 }
01258
01259
01260
01261
01262 void
01263 asim_straight_ellips( ASDrawContext *ctx, int x, int y, int rx, int ry, Bool fill )
01264 {
01265 if( ctx && rx > 0 && ry > 0 &&
01266 x + rx >= 0 && y+ry >= 0 &&
01267 x - rx < ctx->canvas_width && y - ry < ctx->canvas_height )
01268 {
01269 int max_y = ry ;
01270 int orig_x = x, orig_y = y, orig_rx = rx ;
01271 #ifdef HAVE_LONG_LONG
01272 Long64_t rx2 = rx*rx, ry2 = ry * ry, d ;
01273 #else
01274 long rx2 = rx*rx, ry2 = ry * ry, d ;
01275 #endif
01276
01277 #if 1
01278 if (y + ry > ctx->canvas_height && y - ry < 0)
01279 max_y = max (y, ctx->canvas_height - y);
01280 #endif
01281 #if 0
01282 if( fill )
01283 {
01284 long y1 = 0;
01285 long x1 = rx-1;
01286 long ty = rx*rx ;
01287 long tx = x1*x1 ;
01288
01289 do
01290 {
01291 while( tx > ty && x1 > 0 )
01292 {
01293 tx -= (x1<<1)+1 ;
01294 --x1 ;
01295 }
01296 CTX_FILL_HLINE(ctx,x-x1,y+y1,x+x1,255);
01297 CTX_FILL_HLINE(ctx,x-x1,y-y1,x+x1,255);
01298
01299 d = (y1<<1)+1 ;
01300
01301 if( rx != ry )
01302 d = (d*rx2)/ry2 ;
01303 ty -= (long)d;
01304
01305 }while( ++y1 < max_y );
01306 }
01307 #endif
01308
01309 asim_start_path( ctx );
01310 asim_move_to( ctx, x+rx, y );
01311 LOCAL_DEBUG_OUT( "x = %d, y = %d, rx = %d, ry = %d", x, y, rx, ry );
01312
01313 #ifndef HAVE_LONG_LONG
01314 if( (rx == ry && (rx > 16000 || ry > 16000 || x < -16000 || y < -16000 || x > 16000 || y > 16000)) ||
01315 (rx != ry && (rx > 1000 || ry > 1000 || x > 1000 || y > 1000 || x < -1000 || y < -1000)) )
01316 {
01317 int drx = rx*142 ;
01318
01319 int dry = ry*142 ;
01320 LOCAL_DEBUG_OUT( "drx = %d, dry = %d", drx, dry );
01321 rx = rx << 8 ;
01322 ry = ry << 8 ;
01323 x = x << 8 ;
01324 y = y << 8 ;
01325 ctx_draw_bezier( ctx, x+rx, y, x+rx, y+dry, x+drx, y+ry, x, y+ry );
01326 ctx_draw_bezier( ctx, x, y+ry, x-drx, y+ry, x-rx, y+dry, x-rx, y );
01327 ctx_draw_bezier( ctx, x-rx, y, x-rx, y-dry, x-drx, y-ry, x, y-ry );
01328 ctx_draw_bezier( ctx, x, y-ry, x+drx, y-ry, x+rx, y-dry, x+rx, y );
01329
01330 }else
01331 #endif
01332 {
01333 x = x<<4 ;
01334 y = y<<4 ;
01335 rx = rx<<4 ;
01336 ry = ry<<4 ;
01337 max_y = (max_y << 4) + 4;
01338
01339 {
01340 long min_r = rx - 1, max_r = rx + 1 ;
01341 long y1 = 0;
01342 long x1 = max_r;
01343 long min_ty = min_r * min_r ;
01344 long max_ty = max_r * max_r ;
01345 long tx = max_ty ;
01346
01347 do
01348 {
01349 long start_tx, start_x1 ;
01350 while( tx > max_ty && x1 > 0 )
01351 {
01352 --x1;
01353 tx -= (x1<<1)+1 ;
01354 }
01355 start_tx = tx ;
01356 start_x1 = x1 ;
01357
01358
01359 while( tx > min_ty && x1 >= 0)
01360 {
01361 render_supersampled_pixel( ctx, (x-x1)<<4, (y+y1)<<4 );
01362 render_supersampled_pixel( ctx, (x-x1)<<4, (y-y1)<<4 );
01363 render_supersampled_pixel( ctx, (x+x1)<<4, (y+y1)<<4 );
01364 render_supersampled_pixel( ctx, (x+x1)<<4, (y-y1)<<4 );
01365 --x1;
01366 tx -= (x1<<1)+1 ;
01367 }
01368 tx = start_tx ;
01369 x1 = start_x1 ;
01370 d = ((y1<<1)+1);
01371 if( rx != ry )
01372 d = (d*rx2)/ry2 ;
01373 min_ty -= (long)d;
01374 max_ty -= (long)d;
01375 }while( ++y1 <= max_y );
01376 }
01377 }
01378 asim_apply_path( ctx, orig_x+orig_rx, orig_y, fill, orig_x, orig_y, CTX_ELLIPS_FILL_THRESHOLD );
01379 }
01380 }
01381
01382
01383 void
01384 asim_circle( ASDrawContext *ctx, int x, int y, int r, Bool fill )
01385 {
01386 asim_straight_ellips( ctx, x, y, r, r, fill );
01387 }
01388
01389
01390 void
01391 asim_ellips( ASDrawContext *ctx, int x, int y, int rx, int ry, int angle, Bool fill )
01392 {
01393 while( angle >= 360 )
01394 angle -= 360 ;
01395 while( angle < 0 )
01396 angle += 360 ;
01397
01398 if( angle == 0 || angle ==180 || rx == ry )
01399 {
01400 asim_straight_ellips( ctx, x, y, rx, ry, False );
01401 if( angle == 180 )
01402 asim_move_to( ctx, x-rx, y );
01403 return;
01404 }
01405 if( angle == 90 || angle == 270 )
01406 {
01407 asim_straight_ellips( ctx, x, y, ry, rx, False );
01408 asim_move_to( ctx, x, y + (angle == 90?-rx:rx) );
01409 return;
01410 }
01411
01412 if( ctx && rx > 0 && ry > 0 )
01413 {
01414 int dx0 = rx, dy0 = ry, dx1 = 0, dy1 = rx*4/3 ;
01415 int x0, y0, x1down, y1down, x2down, y2down, x3, y3, x2up, y2up, x1up, y1up ;
01416 int ry4 = (ry<<2)/3 ;
01417 int sin_val = asim_sin(angle);
01418 int cos_val = asim_sin(angle+90);
01419 if(sin_val < 0)
01420 sin_val = -sin_val ;
01421 if(cos_val < 0)
01422 cos_val = -cos_val ;
01423 dx0 = (rx*cos_val)>>8;
01424 dy0 = (rx*sin_val)>>8;
01425 dx1 = (ry4*sin_val)>>8;
01426 dy1 = (ry4*cos_val)>>8;
01427 if( angle < 180 )
01428 {
01429 dy0 = -dy0 ;
01430 dx1 = -dx1 ;
01431 }
01432 if( angle > 90 && angle < 270 )
01433 {
01434 dx0 = -dx0 ;
01435 dy1 = -dy1 ;
01436 }
01437 x = x << 8;
01438 y = y << 8;
01439 x0 = x + dx0 ;
01440 y0 = y + dy0 ;
01441 x3 = x - dx0 ;
01442 y3 = y - dy0 ;
01443 x1down = x0 + dx1 ;
01444 y1down = y0 - dy1 ;
01445 x2down = x3 + dx1 ;
01446 y2down = y3 - dy1 ;
01447 x2up = x3 - dx1 ;
01448 y2up = y3 + dy1 ;
01449 x1up = x0 - dx1 ;
01450 y1up = y0 + dy1 ;
01451
01452
01453 asim_start_path( ctx );
01454 asim_move_to( ctx, x0>>8, y0>>8 );
01455 ctx_draw_bezier( ctx, x0, y0, x1down, y1down, x2down, y2down, x3, y3 );
01456 ctx_draw_bezier( ctx, x3, y3, x2up, y2up, x1up, y1up, x0, y0 );
01457 asim_apply_path( ctx, x0>>8, y0>>8, fill, x, y, CTX_ELLIPS_FILL_THRESHOLD );
01458 }
01459 }
01460
01461 void
01462 asim_ellips2( ASDrawContext *ctx, int x, int y, int rx, int ry, int angle, Bool fill )
01463 {
01464 Bool direction = 1 ;
01465
01466 while( angle >= 360 )
01467 angle -= 360 ;
01468 while( angle < 0 )
01469 angle += 360 ;
01470
01471 if( angle == 0 || angle ==180 || rx == ry )
01472 {
01473 asim_straight_ellips( ctx, x, y, rx, ry, fill );
01474 if( angle == 180 )
01475 asim_move_to( ctx, x-rx, y );
01476 return;
01477 }
01478 if( angle == 90 || angle == 270 )
01479 {
01480 asim_straight_ellips( ctx, x, y, ry, rx, fill );
01481 asim_move_to( ctx, x, y + (angle == 90?-rx:rx) );
01482 return;
01483 }
01484
01485 if( angle > 180 )
01486 angle -= 180 ;
01487 if( angle > 90 )
01488 {
01489 angle = 180-angle ;
01490 direction = -1 ;
01491 }
01492
01493
01494 if( ctx && rx > 0 && ry > 0 )
01495 {
01496 int sin90 = 0x00010000 ;
01497 double sin_val = (double)asim_sin(angle)/(double)sin90;
01498 double cos_val = (double)asim_sin(angle+90)/(double)sin90;
01499 double rx2 = rx*rx ;
01500 double ry2 = ry*ry ;
01501 double c2 = rx2 - ry2 ;
01502 double xc2 = (c2 * cos_val)*cos_val ;
01503 double yc2 = (c2 * sin_val)*sin_val ;
01504 double A = rx2 - xc2 ;
01505 double B = rx2 - yc2 ;
01506 double C = -c2*sin_val*cos_val ;
01507 double F = -rx2*ry2 ;
01508 int yt = asim_sqrt(A);
01509 int xt = (int)-C/yt ;
01510 int xr = asim_sqrt(B);
01511 int yr = (int)-C/xr ;
01512 int x1 ;
01513 int x2 ;
01514 int line = yt;
01515 int last_med_dd1 = 0 ;
01516 int last_med_dd2 = 0 ;
01517 int y1 ;
01518 double A2 = 2.*A ;
01519 double BB;
01520 double CC = C*(double)((line<<1)-1);
01521
01522
01523 xt = (int)((A-CC)/A2) ;
01524 y1 = line*direction ;
01525 BB = B*(double)line*(double)line + F - B*(double)line - (B/4.);
01526 x1 = xt+1 ;
01527 x2 = xt-1 ;
01528 --yr ;
01529
01530 while( line >= -1 )
01531 {
01532 double d ;
01533 int dx1 = 0, dx2 = 0 ;
01534 d = A*(double)x1*(double)x1 + BB +CC*(double)x1;
01535 #ifdef DEBUG_ELLIPS
01536 fprintf( stderr, "line = %d, d1 = %f", y-line, d );
01537 #endif
01538 if( d < 0 )
01539 {
01540 int aa = (int)((A-A2*(double)x1-CC)*255/A2);
01541 int dd = (int)(-aa-(double)(d*255/A2)) ;
01542 int med_dd = (dd>>1)+1;
01543
01544 if( last_med_dd1 > 0 )
01545 {
01546
01547 med_dd = (2*med_dd+last_med_dd1)/3 ;
01548 }
01549 ++dx1 ;
01550 #ifdef DEBUG_ELLIPS
01551 fprintf( stderr, " -> d1 = %f, dx1 = %d, aa = %d, dd = %d, med_dd = %d\n", d, dx1, aa, dd, med_dd );
01552 #endif
01553 if( med_dd+aa > dd )
01554 {
01555 int v = (dd-med_dd)*255/(aa+255) ;
01556 CTX_PUT_PIXEL( ctx, x+(x1-1), y-y1, 255-v ) ;
01557 CTX_PUT_PIXEL( ctx, x-(x1-1), y+y1, 255-v ) ;
01558 CTX_PUT_PIXEL( ctx, x+(x1-2), y-y1, v ) ;
01559 CTX_PUT_PIXEL( ctx, x-(x1-2), y+y1, v ) ;
01560 dx1 = 2 ;
01561 #ifdef DEBUG_ELLIPS
01562 fprintf( stderr, "\t\t dx1 = %d, v = %d\n", dx1, v );
01563 #endif
01564 }else
01565 while( dd > -(aa>>1) )
01566 {
01567 int v ;
01568 v = ( dd >= med_dd )? dd-med_dd: med_dd-dd ;
01569 v = v*255/med_dd ;
01570 if( v < 0 || v > 255)
01571 v = 250 ;
01572
01573 CTX_PUT_PIXEL( ctx, x+(x1-dx1), y-y1, 255-v ) ;
01574 CTX_PUT_PIXEL( ctx, x-(x1-dx1), y+y1, 255-v ) ;
01575 if( x1 >= xt && dd > med_dd )
01576 {
01577 CTX_PUT_PIXEL( ctx, x+(x1-dx1), y-(y1+direction), v ) ;
01578 CTX_PUT_PIXEL( ctx, x-(x1-dx1), y+(y1+direction), v ) ;
01579 }
01580 ++dx1 ;
01581 #ifdef DEBUG_ELLIPS
01582 fprintf( stderr, "\t\t dx1 = %d, aa = %d, dd = %d, med_dd = %d, v = %d, x = %d\n", dx1, aa, dd, med_dd, v, x+(x1-dx1) );
01583 #endif
01584 aa += 255 ;
01585 dd -= aa ;
01586 }
01587 x1 -= (dx1>>1)-1 ;
01588 last_med_dd1 = med_dd ;
01589 }
01590
01591 d = A*(double)(x2+1)*(double)(x2+1) + BB +CC*(double)(x2+1) ;
01592 if( line > yr )
01593 {
01594 #ifdef DEBUG_ELLIPS
01595 fprintf( stderr, "line = %d, d2 = %f\n", y-line, d );
01596 #endif
01597 if( d < 0 )
01598 {
01599 int aa = (int)((A+A2*(double)x2+CC)*255/A2);
01600 int dd = (int)(aa+(double)(d*255/A2)) ;
01601 int med_dd = dd/2 - 1;
01602
01603 if( last_med_dd2 > 0 )
01604 {
01605
01606 med_dd = (med_dd*2+last_med_dd2)/3 ;
01607 }
01608 dx2 = 1;
01609 #ifdef DEBUG_ELLIPS
01610 fprintf( stderr, " -> d2 = %f, x2 = %d, dx2 = %d, aa = %d, dd = %d, med_dd = %d\n", d, x2, dx2, aa, dd, med_dd );
01611 #endif
01612 if( med_dd-aa < dd )
01613 {
01614 int v = (med_dd-dd)*255/(aa+255) ;
01615 CTX_PUT_PIXEL( ctx, x+(x2+2), y-y1, 255-v ) ;
01616 CTX_PUT_PIXEL( ctx, x-(x2+2), y+y1, 255-v ) ;
01617 CTX_PUT_PIXEL( ctx, x+(x2+3), y-y1, v ) ;
01618 CTX_PUT_PIXEL( ctx, x-(x2+3), y+y1, v ) ;
01619 dx2 = 2 ;
01620 #ifdef DEBUG_ELLIPS
01621 fprintf( stderr, "\t\t dx2 = %d, v = %d\n", dx2, v );
01622 #endif
01623 }else while( dd < aa/2 )
01624 {
01625 int v ;
01626 v = ( dd >= med_dd )? dd-med_dd: med_dd-dd ;
01627 v = v*255/-med_dd ;
01628 if( v < 0 || v > 255)
01629 v = 250 ;
01630 #ifdef DEBUG_ELLIPS
01631 fprintf( stderr, "\t\t dx2 = %d, aa = %d, dd = %d, med_dd = %d, v = %d, x = %d\n", dx2, aa, dd, med_dd, v, x+(x2+dx2) );
01632 #endif
01633 ++dx2;
01634 CTX_PUT_PIXEL( ctx, x+(x2+dx2), y-y1, 255-v ) ;
01635 CTX_PUT_PIXEL( ctx, x-(x2+dx2), y+y1, 255-v ) ;
01636 if( x2 <= xt && dd < med_dd )
01637 {
01638 CTX_PUT_PIXEL( ctx, x+(x2+dx2), y-(y1+direction), v ) ;
01639 CTX_PUT_PIXEL( ctx, x-(x2+dx2), y+(y1+direction), v ) ;
01640 }
01641 aa += 255 ;
01642 dd += aa ;
01643 }
01644 x2 += (dx2>>1)-1 ;
01645 last_med_dd2 = med_dd ;
01646 }
01647 }else if( line < yr )
01648 {
01649 #ifdef DEBUG_ELLIPS
01650 fprintf( stderr, "line = %d, BELOW: d2 = %f\n", y-line, d );
01651 #endif
01652 if( d > 0. )
01653 {
01654 int aa = (int)((A-A2*(double)(x2)-CC)*255./A2);
01655 int dd = (int)(aa+(double)(d*255./A2)) ;
01656 int med_dd = dd/2+1;
01657
01658 if( last_med_dd2 > 0 )
01659 med_dd = (med_dd*2+last_med_dd2)/3 ;
01660
01661 dx2 = -1 ;
01662 #ifdef DEBUG_ELLIPS
01663 fprintf( stderr, " ->BELOW: d2 = %f, dx2 = %d, aa = %d, dd = %d, med_dd = %d\n", d, dx2, aa, dd, med_dd );
01664 #endif
01665 if( med_dd-aa > dd )
01666 {
01667 int v = (dd-med_dd)*255/(-aa+255) ;
01668 #ifdef DEBUG_ELLIPS
01669 fprintf( stderr, "\t\t BELOW: dx2 = %d, v = %d\n", dx2, v );
01670 #endif
01671 CTX_PUT_PIXEL( ctx, x+(x2-1), y-y1, 255-v ) ;
01672 CTX_PUT_PIXEL( ctx, x-(x2-1), y+y1, 255-v ) ;
01673 CTX_PUT_PIXEL( ctx, x+(x2-2), y-y1, v ) ;
01674 CTX_PUT_PIXEL( ctx, x-(x2-2), y+y1, v ) ;
01675 dx2 = -2 ;
01676 }else while( dd > aa/2 )
01677 {
01678 int v ;
01679 v = ( dd >= med_dd )? dd-med_dd: med_dd-dd ;
01680 v = v*255/med_dd ;
01681 if( v < 0 || v > 255)
01682 v = 250 ;
01683 #ifdef DEBUG_ELLIPS
01684 fprintf( stderr, "\t\tBELOW: dx2 = %d, aa = %d, dd = %d, med_dd = %d, v = %d, x = %d\n", dx2, aa, dd, med_dd, v, x+(x2+dx2) );
01685 #endif
01686 CTX_PUT_PIXEL( ctx, x+(x2+dx2), y-y1, 255-v ) ;
01687 CTX_PUT_PIXEL( ctx, x-(x2+dx2), y+y1, 255-v ) ;
01688 --dx2;
01689 aa += 255 ;
01690 dd += aa ;
01691 }
01692 x2 += (dx2/2)+1 ;
01693 last_med_dd2 = med_dd ;
01694 }
01695 }else
01696 {
01697 x2 = xr+2 ;
01698 #ifdef DEBUG_ELLIPS
01699 fprintf( stderr, "\t\t BELOW: x2 = %d, xr = %d\n", x2,xr);
01700 #endif
01701 CTX_PUT_PIXEL( ctx, x+xr, y-y1, 255 ) ;
01702 CTX_PUT_PIXEL( ctx, x-xr, y+y1, 255 ) ;
01703 last_med_dd2 = 0 ;
01704 }
01705 #ifdef DEBUG_ELLIPS
01706 fprintf( stderr, "dx1 = %d, x1 = %d, dx2 = %d, x2 = %d\n", dx1, x1, dx2, x2 );
01707 #endif
01708 if( fill )
01709 {
01710 CTX_FILL_HLINE(ctx,x+(x1-2),y-y1,x+x2-1,255);
01711 CTX_FILL_HLINE(ctx,x-x2-1,y+y1,x-(x1-2),255);
01712 }
01713
01714 CC -= 2.*C ;
01715 BB -= B*(double)((line-1)<<1) ;
01716 y1 -= direction ;
01717 --line ;
01718 }
01719 }
01720 }
01721
01722
01723
01724
01725
01726 void
01727 asim_flood_fill( ASDrawContext *ctx, int x, int y, CARD32 min_val, CARD32 max_val )
01728 {
01729 if( ctx && x >= 0 && x < ctx->canvas_width && y >= 0 && y < ctx->canvas_height )
01730 {
01731 int x0 = x, x1 = x ;
01732 int cw = ctx->canvas_width ;
01733 CARD32 *data = CTX_SELECT_CANVAS(ctx) + y*cw ;
01734 while( x0 >= 0 && data[x0] <= max_val && data[x0] >= min_val ) --x0;
01735 ++x0 ;
01736 while( x1 < cw && data[x1] <= max_val && data[x1] >= min_val ) ++x1;
01737 --x1 ;
01738 LOCAL_DEBUG_OUT( "x = %d, y = %d, data[x] = 0x%X, x0 = %d, x1 = %d", x, y, data[x], x0, x1 );
01739
01740 if( x0 <= x1 )
01741 ctx_flood_fill( ctx, x0, y, x1, min_val, max_val );
01742 }
01743 }
01744
01745 void
01746 asim_rectangle( ASDrawContext *ctx, int x, int y, int width, int height )
01747 {
01748 asim_move_to( ctx, x, y );
01749 asim_line_to_generic( ctx, x+width, y, ctx_draw_line_solid);
01750 asim_line_to_generic( ctx, x+width, y+height, ctx_draw_line_solid);
01751 asim_line_to_generic( ctx, x, y+height, ctx_draw_line_solid);
01752 asim_line_to_generic( ctx, x, y, ctx_draw_line_solid);
01753 }
01754
01755
01756
01757
01758
01759
01760
01761
01762
01763
01764
01765 #ifdef TEST_ASDRAW
01766 #include "afterimage.h"
01767
01768
01769
01770 typedef int Int_t;
01771 typedef unsigned int UInt_t;
01772 typedef int Bool_t;
01773
01774 static ASDrawContext *create_draw_context_argb32(ASImage *im, ASDrawTool *brush)
01775 {
01776
01777
01778 ASDrawContext *ctx = safecalloc (1, sizeof(ASDrawContext));
01779
01780 ctx->canvas_width = im->width;
01781 ctx->canvas_height = im->height;
01782 ctx->canvas = im->alt.argb32;
01783 ctx->scratch_canvas = 0;
01784
01785 ctx->flags = ASDrawCTX_CanvasIsARGB;
01786 asim_set_custom_brush_colored( ctx, brush);
01787 return ctx;
01788 }
01789
01790
01791 ASImage *TASImage_DrawCircle(ASVisual *asv, ASImage *fImage, Int_t x, Int_t y, Int_t r, const char *col, Int_t thick)
01792 {
01793
01794
01795 thick = !thick ? 1 : thick;
01796 Int_t sz = thick*thick;
01797 CARD32 *matrix;
01798 int i;
01799 ASImage *img = 0;
01800 ASDrawContext *ctx;
01801
01802 ARGB32 color;
01803 parse_argb_color(col, &color);
01804 ASDrawTool brush;
01805
01806 matrix = malloc (sizeof(CARD32)*sz);
01807
01808 for (i = 0; i < sz; i++) {
01809 matrix[i] = (CARD32)color;
01810 }
01811
01812 brush.matrix = matrix;
01813 brush.height = brush.width = thick > 0 ? thick : 1;
01814 brush.center_y = brush.center_x = thick > 0 ? thick/2 : 0;
01815
01816 img = tile_asimage(asv, fImage, 0, 0, fImage->width, fImage->height,
01817 0, ASA_ARGB32, 0, ASIMAGE_QUALITY_DEFAULT);
01818
01819 ctx = create_draw_context_argb32(img, &brush);
01820
01821 asim_circle(ctx, x, y, r, thick < 0);
01822 asim_cube_bezier(ctx, x+50, y+50, x+100, y+100, x+50, y+100);
01823 asim_move_to(ctx, x, y+200);
01824 asim_line_to_aa(ctx, x+200, y+100);
01825 asim_line_to_aa(ctx, x+200, y+200);
01826 asim_line_to_aa(ctx, x, y+200);
01827
01828 free (matrix);
01829
01830
01831 return img;
01832 }
01833
01834
01835
01836
01837
01838 int main(int argc, char **argv )
01839 {
01840 ASVisual *asv ;
01841 ASImage *back = NULL ;
01842 ASImage *drawing1 = NULL ;
01843 ASImage *merged_im = NULL ;
01844 ASImageLayer *layers ;
01845 int layers_num = 0, i;
01846 int screen = 0, depth = 0;
01847
01848 ASDrawContext *ctx ;
01849
01850 #define DRAW_TEST_SIZE 800
01851
01852 set_output_threshold( 10 );
01853
01854 #ifndef X_DISPLAY_MISSING
01855 dpy = XOpenDisplay(NULL);
01856 screen = DefaultScreen(dpy);
01857 depth = DefaultDepth( dpy, screen );
01858 #endif
01859
01860 asv = create_asvisual( dpy, screen, depth, NULL );
01861
01862
01863 back = create_asimage( DRAW_TEST_SIZE, DRAW_TEST_SIZE, 100 );
01864 back->back_color = ARGB32_White ;
01865 drawing1 = create_asimage( DRAW_TEST_SIZE, DRAW_TEST_SIZE, 100 );
01866 drawing1->back_color = ARGB32_Black ;
01867
01868
01869 ctx = create_asdraw_context(DRAW_TEST_SIZE, DRAW_TEST_SIZE);
01870
01871 #if 1
01872
01873 #if 1
01874 asim_move_to( ctx, 0, 0 );
01875 asim_line_to_aa( ctx, 200, 200 );
01876 asim_line_to_aa( ctx, 100, 10 );
01877 asim_line_to_aa( ctx, 10, 300 );
01878 asim_line_to_aa( ctx, 15, 400 );
01879 asim_move_to(ctx, 15, 420);
01880 asim_line_to_aa( ctx, 200, 410 );
01881 asim_line_to_aa( ctx, 400, 440 );
01882
01883 asim_move_to(ctx, 10, 0);
01884 asim_set_brush( ctx, 1 );
01885 asim_line_to_aa( ctx, 210, 200 );
01886 asim_line_to_aa( ctx, 110, 10 );
01887 asim_line_to_aa( ctx, 20, 300 );
01888 asim_line_to_aa( ctx, 25, 400 );
01889 asim_move_to(ctx, 15, 430);
01890 asim_line_to_aa( ctx, 200, 420 );
01891 asim_line_to_aa( ctx, 400, 450 );
01892
01893 asim_move_to(ctx, 20, 0);
01894 asim_set_brush( ctx, 2 );
01895 asim_line_to_aa( ctx, 220, 200 );
01896 asim_line_to_aa( ctx, 120, 10 );
01897
01898 #endif
01899 asim_move_to(ctx, 120, 10);
01900 asim_set_brush( ctx, 2 );
01901
01902 asim_line_to_aa( ctx, 30, 300 );
01903 #if 1
01904 asim_line_to_aa( ctx, 35, 400 );
01905 asim_move_to(ctx, 15, 440);
01906 asim_line_to_aa( ctx, 200, 430 );
01907 asim_line_to_aa( ctx, 400, 460 );
01908
01909
01910
01911
01912 asim_move_to(ctx, 200, 0 );
01913
01914 asim_set_brush( ctx, 0 );
01915 asim_line_to( ctx, 400, 200 );
01916 asim_line_to( ctx, 300, 10 );
01917 asim_line_to( ctx, 210, 300 );
01918 asim_line_to( ctx, 215, 400 );
01919 asim_move_to(ctx, 15, 450);
01920 asim_line_to( ctx, 200, 440 );
01921 asim_line_to( ctx, 400, 470 );
01922
01923 asim_move_to(ctx, 210, 0);
01924 asim_set_brush( ctx, 1 );
01925 asim_line_to( ctx, 410, 200 );
01926 asim_line_to( ctx, 310, 10 );
01927 asim_line_to( ctx, 220, 300 );
01928 asim_line_to( ctx, 225, 400 );
01929 asim_move_to(ctx, 15, 460);
01930 asim_line_to( ctx, 200, 450 );
01931 asim_line_to( ctx, 400, 480 );
01932
01933 asim_move_to(ctx, 220, 0);
01934 asim_set_brush( ctx, 2 );
01935 asim_line_to( ctx, 420, 200 );
01936 asim_line_to( ctx, 320, 10 );
01937 asim_line_to( ctx, 230, 300 );
01938 asim_line_to( ctx, 235, 400 );
01939 asim_move_to(ctx, 15, 470);
01940 asim_line_to( ctx, 200, 460 );
01941 asim_line_to( ctx, 400, 490 );
01942
01943 asim_set_brush( ctx, 0 );
01944 asim_circle( ctx, 600, 110, 80, False );
01945 asim_circle( ctx, 600, 110, 50, False );
01946 asim_circle( ctx, 600, 110, 20, False );
01947 asim_circle( ctx, 600, 110, 1, False );
01948
01949 asim_set_brush( ctx, 1 );
01950 asim_circle( ctx, 600, 110, 90, False );
01951 asim_circle( ctx, 600, 110, 60, False );
01952 asim_circle( ctx, 600, 110, 30, False );
01953 asim_circle( ctx, 600, 110, 5, False );
01954
01955 asim_set_brush( ctx, 2 );
01956 asim_circle( ctx, 600, 110, 100, False );
01957 asim_circle( ctx, 600, 110, 70, False );
01958 asim_circle( ctx, 600, 110, 40, False );
01959 asim_circle( ctx, 600, 110, 10, False );
01960
01961 asim_set_brush( ctx, 0 );
01962
01963
01964
01965 asim_circle( ctx, 595, 550, 200, False );
01966 i = 30 ;
01967
01968 {
01969
01970
01971 for( i = 3 ; i < 180 ; i+=5 )
01972 {
01973
01974
01975
01976
01977
01978 asim_ellips2( ctx, 595, 550, 198, 60, i, False );
01979
01980
01981
01982 }
01983 }
01984 asim_circle( ctx, 705, 275, 90, True );
01985
01986
01987 asim_circle( ctx, -40000, 500, 40500, False );
01988 asim_circle( ctx, -10000, 500, 10499, False );
01989
01990 asim_ellips2( ctx, -1000, 500, 1500, 100, 2, False );
01991
01992 asim_flood_fill( ctx, 664, 166, 0, 126 );
01993 asim_flood_fill( ctx, 670, 77, 0, 126 );
01994 asim_flood_fill( ctx, 120, 80, 0, 126 );
01995 asim_flood_fill( ctx, 300, 460, 0, 126 );
01996
01997 #endif
01998 #endif
01999 #if 1
02000
02001 apply_asdraw_context( drawing1, ctx, SCL_DO_ALPHA );
02002
02003 layers_num = 2 ;
02004 layers = create_image_layers( layers_num );
02005
02006 layers[0].im = back ;
02007 layers[1].im = drawing1 ;
02008 layers[0].clip_width = DRAW_TEST_SIZE ;
02009 layers[0].clip_height = DRAW_TEST_SIZE ;
02010 layers[1].clip_width = DRAW_TEST_SIZE ;
02011 layers[1].clip_height = DRAW_TEST_SIZE ;
02012
02013 merged_im = merge_layers( asv, layers, layers_num,
02014 DRAW_TEST_SIZE, DRAW_TEST_SIZE,
02015 ASA_ASImage,
02016 0, ASIMAGE_QUALITY_DEFAULT );
02017
02018 #if 1
02019 {
02020 ASImage *overlayed_im = TASImage_DrawCircle(asv, merged_im, 84, 299, 80, "blue", -1);
02021 ASImage2file( overlayed_im, NULL, "test_asdraw.overlayed.png", ASIT_Png, NULL );
02022 destroy_asimage( &overlayed_im );
02023 }
02024 #endif
02025 ASImage2file( merged_im, NULL, "test_asdraw.merged.png", ASIT_Png, NULL );
02026 destroy_asimage( &merged_im );
02027 #endif
02028
02029 return 0;
02030 }
02031
02032
02033 #endif
02034