home *** CD-ROM | disk | FTP | other *** search
/ Acorn User 10 / AU_CD10.iso / Archived / Updates / Flash / flashplayer / flashlib / c++ / graphic32 < prev    next >
Encoding:
Text File  |  2000-03-24  |  16.5 KB  |  698 lines

  1. ////////////////////////////////////////////////////////////
  2. // Flash Plugin and Player
  3. // Copyright (C) 1998 Olivier Debon
  4. //
  5. // This program is free software; you can redistribute it and/or
  6. // modify it under the terms of the GNU General Public License
  7. // as published by the Free Software Foundation; either version 2
  8. // of the License, or (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18. //
  19. ///////////////////////////////////////////////////////////////
  20. //  Author : Olivier Debon  <odebon@club-internet.fr>
  21. //
  22.  
  23. #include "swf.h"
  24. #include "graphic32.h"
  25.  
  26. #ifdef RCSID
  27. static char *rcsid = "$Id: graphic.cc,v 1.5 1999/09/03 15:17:40 ode Exp $";
  28. #endif
  29.  
  30. #include "sqrt.h"
  31.  
  32. #define FULL_AA
  33.  
  34. #define PRINT 0
  35.  
  36. typedef unsigned long TYPE;
  37.  
  38. #define HBP
  39.  
  40. // Public
  41.  
  42. GraphicDevice32::GraphicDevice32(FlashDisplay *fd) : GraphicDevice(fd)
  43. {
  44. }
  45.  
  46. GraphicDevice32::~GraphicDevice32()
  47. {
  48. }
  49.  
  50. long
  51. GraphicDevice32::allocColor(Color color)
  52. {
  53.     return (color.red) | (color.green)<<8 | color.blue << 16;
  54. }
  55.  
  56. Color
  57. GraphicDevice32::getColor(unsigned long c)
  58. {
  59.   Color color;
  60.  
  61.   color.red = c & 0xff;
  62.   color.green = (c >> 8) & 0xff;
  63.   color.blue = c >> 16;
  64.   return color;
  65. }
  66.  
  67. void
  68. GraphicDevice32::clearCanvas()
  69. {
  70.     TYPE  pixel;
  71.     TYPE *point,*p;
  72.     long                 h, w,n;
  73.  
  74.     if (!bgInitialized) return;
  75.  
  76.     pixel = allocColor(backgroundColor);
  77.  
  78.     // The following allows to test clipping
  79.     //for(point = (TYPE *)canvasBuffer,n=0; n<targetHeight*bpl/2; point++,n++) *point = 0xfe00;
  80.  
  81.     point = (TYPE *)(canvasBuffer + clip_rect.ymin * bpl) + clip_rect.xmin;
  82.     w = clip_rect.xmax - clip_rect.xmin;
  83.     h = clip_rect.ymax - clip_rect.ymin;
  84.  
  85.     while (h--) {
  86.         p = point;
  87.         n = w;
  88.         while (n--) {
  89.             *p++ = pixel;
  90.         }
  91.  
  92.         point = (TYPE *)((char *)point + bpl);
  93.     }
  94.  
  95.     flashDisplay->flash_refresh = 1;
  96.     flashDisplay->clip_x = clip_rect.xmin;
  97.     flashDisplay->clip_y = clip_rect.ymin;
  98.     flashDisplay->clip_width  = clip_rect.xmax-clip_rect.xmin;
  99.     flashDisplay->clip_height = clip_rect.ymax-clip_rect.ymin;
  100. }
  101.  
  102. void
  103. GraphicDevice32::fillLineAA(FillStyleDef *f, long y, long start, long end)
  104. {
  105.     register long   n;
  106.     TYPE *line;
  107.     TYPE *point,pixel;
  108.     unsigned int alpha, start_alpha,end_alpha;
  109.  
  110.     if (clip(y,start,end)) return;
  111.  
  112.     line = (TYPE *)(canvasBuffer + bpl*y);
  113.  
  114.     alpha = f->color.alpha;
  115.     pixel = f->color.pixel;
  116.  
  117.     if (alpha == ALPHA_OPAQUE) {
  118.  
  119.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  120.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  121.  
  122.         start >>= FRAC_BITS;
  123.         end >>= FRAC_BITS;
  124.  
  125.         point = &line[start];
  126.  
  127.         if (start == end) {
  128.             *point = mix_alpha(*point, pixel, start_alpha + end_alpha - 255);
  129.         } else {
  130.             n = end-start;
  131.             if (start_alpha < 255) {
  132.                 *point = mix_alpha(*point, pixel, start_alpha);
  133.                 point++;
  134.                 n--;
  135.             }
  136.             while (n > 0) {
  137.                 *point = pixel;
  138.                 point++;
  139.                 n--;
  140.             }
  141.             if (end_alpha > 0) {
  142.                 *point = mix_alpha(*point, pixel, end_alpha);
  143.             }
  144.         }
  145.     } else {
  146.  
  147.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  148.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  149.  
  150.         start >>= FRAC_BITS;
  151.         end >>= FRAC_BITS;
  152.  
  153.         point = &line[start];
  154.  
  155.         if (start == end) {
  156.             *point = mix_alpha(*point, pixel,
  157.                                ((start_alpha + end_alpha - 255) * alpha) >> 8);
  158.         } else {
  159.             n = end-start;
  160.             if (start_alpha < 255) {
  161.                 *point = mix_alpha(*point, pixel, (start_alpha * alpha) >> 8);
  162.                 point++;
  163.                 n--;
  164.             }
  165.             while (n > 0) {
  166.                 *point = mix_alpha(*point, pixel, alpha);
  167.                 point++;
  168.                 n--;
  169.             }
  170.             if (end_alpha > 0) {
  171.                 *point = mix_alpha(*point, pixel, (end_alpha * alpha) >> 8);
  172.             }
  173.         }
  174.     }
  175. }
  176.  
  177. void
  178. GraphicDevice32::fillLine(FillStyleDef *f, long y, long start, long end)
  179. {
  180.     register long   n;
  181.         TYPE *line,*point;
  182.         TYPE pixel;
  183.         unsigned int alpha;
  184.  
  185.     if (clip(y,start,end)) return;
  186.  
  187.         start >>= FRAC_BITS;
  188.         end >>= FRAC_BITS;
  189.  
  190.     line = (TYPE *)(canvasBuffer + bpl*y);
  191.     point = &line[start];
  192.     n = end-start;
  193.         pixel = f->color.pixel;
  194.         alpha = f->color.alpha;
  195.         if (alpha == ALPHA_OPAQUE) {
  196.             while (n--) {
  197.         *point = pixel;
  198.         point++;
  199.             }
  200.         } else {
  201.             while (n--) {
  202.         *point = mix_alpha(*point, pixel, alpha);
  203.         point++;
  204.             }
  205.         }
  206. }
  207.  
  208. /* 16 bit assumed... easy to change */
  209. void
  210. GraphicDevice32::fillLineBitmap(FillStyleDef *f, long y, long start, long end)
  211. {
  212.     int n;
  213.     long x1,y1,dx,dy;
  214.     Matrix *m = &f->bitmap_matrix;
  215.     Bitmap *b = f->bitmap;
  216.     unsigned char *pixels;
  217. //    unsigned short *p;
  218.     unsigned long *p;
  219.     Color *cmap;
  220.     long pixbpl;
  221.     TYPE pixel;
  222.     int offset;
  223.     unsigned char *alpha_table;
  224.  
  225.     /* safety test) */
  226.     if (!b) return;
  227.  
  228.     if (clip(y,start,end)) return;
  229.  
  230.     start /= FRAC;
  231.     end /= FRAC;
  232.     n = end - start;
  233. //    p = (unsigned short *) (this->canvasBuffer + this->bpl*y + start * 2);
  234.     p = (unsigned long *) (this->canvasBuffer + this->bpl*y + start * 4);
  235.  
  236.     /* the coordinates in the image are normalized to 16 bits */
  237. #ifdef HBP
  238.     x1 = start*m->a + y*m->b + m->tx;
  239.     y1 = start*m->c + y*m->d + m->ty;
  240.     dx = m->a;
  241.     dy = m->c;
  242. #else
  243.     x1 = (long) (m->a * start + m->b * y + m->tx);
  244.     y1 = (long) (m->c * start + m->d * y + m->ty);
  245.     dx = (long) (m->a);
  246.     dy = (long) (m->c);
  247. #endif
  248.  
  249.     pixels = b->pixels;
  250.     pixbpl = b->bpl;
  251.     cmap = f->cmap;
  252.  
  253.     if (b->alpha_buf == NULL) {
  254.         while (n) {
  255.             if (x1 >= 0 && y1 >= 0 &&
  256.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  257.  
  258.                 pixel = cmap[pixels[(y1 >> 16) * pixbpl + (x1 >> 16)]].pixel;
  259.                 *p = pixel;
  260.             }
  261.             x1 += dx;
  262.             y1 += dy;
  263.             p++;
  264.             n--;
  265.         }
  266.     } else if (f->alpha_table) {
  267.         alpha_table = f->alpha_table;
  268.         while (n) {
  269.             if (x1 >= 0 && y1 >= 0 &&
  270.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  271.  
  272.                 offset = (y1 >> 16) * pixbpl + (x1 >> 16);
  273.                 pixel = cmap[pixels[offset]].pixel;
  274.                 *p = mix_alpha(*p, pixel, alpha_table[b->alpha_buf[offset]]);
  275.             }
  276.             x1 += dx;
  277.             y1 += dy;
  278.             p++;
  279.             n--;
  280.         }
  281.     } else {
  282.         while (n) {
  283.             if (x1 >= 0 && y1 >= 0 &&
  284.                 (x1 >> 16) < b->width && (y1 >> 16) < b->height) {
  285.  
  286.                 offset = (y1 >> 16) * pixbpl + (x1 >> 16);
  287.                 pixel = cmap[pixels[offset]].pixel;
  288.                 *p = mix_alpha(*p, pixel, b->alpha_buf[offset]);
  289.             }
  290.             x1 += dx;
  291.             y1 += dy;
  292.             p++;
  293.             n--;
  294.         }
  295.     }
  296. }
  297.  
  298.  
  299. /* XXX: clipping should be better handled */
  300. void
  301. GraphicDevice32::fillLineLG(Gradient *grad, long y, long start, long end)
  302. {
  303.     long dr,r,v,r2;
  304.     register long n;
  305.     TYPE *line;
  306.     TYPE *point;
  307.         Color *cp,*ramp;
  308.         Matrix *m = &grad->imat;
  309.         unsigned int start_alpha,end_alpha;
  310.  
  311.     if (clip(y,start,end)) return;
  312.  
  313.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  314.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  315.  
  316.     start /= FRAC;
  317.     end /= FRAC;
  318.  
  319.     n = end-start;
  320.  
  321. #if 1
  322. #define SHIFTIT 10
  323.         r = (((long)m->a) >> 6) * start + (((long)m->b) >> 6) * y + (m->tx >> 6);
  324.         dr = ((long)(m->a)) >> 6;
  325.  
  326. #else
  327. #define SHIFTIT 16
  328.         r = (long) (m->a * start + m->b * y + m->tx);
  329.         dr = (long) (m->a);
  330. #endif
  331.  
  332.         ramp = grad->ramp;
  333.  
  334.         line = (TYPE *)(canvasBuffer + bpl*y);
  335.     point = &line[start];
  336.  
  337.         r2 = r + n * dr;
  338.         if ( ((r | r2) & ~255) == 0 ) {
  339.             if (!grad->has_alpha) {
  340. #ifdef FULL_AA
  341.         if (start_alpha < 255) {
  342.                     v = r>>SHIFTIT;
  343.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
  344.                     point++;
  345.                     r += dr;
  346.             n--;
  347.         }
  348. #endif /* FULL_AA */
  349.                 while (n>0) {
  350.                     v = r>>SHIFTIT;
  351.                     *point = (TYPE)ramp[v].pixel;
  352.                     point++;
  353.                     r += dr;
  354.             n--;
  355.                 }
  356. #ifdef FULL_AA
  357.         if (end_alpha > 0) {
  358.                     v = r>>SHIFTIT;
  359.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
  360.         }
  361. #endif /* FULL_AA */
  362.             } else {
  363.                 while (n--) {
  364.                     v = r>>SHIFTIT;
  365.                     cp = &ramp[v];
  366.                     *point = mix_alpha(*point, cp->pixel, cp->alpha);
  367.                     point++;
  368.                     r += dr;
  369.                 }
  370.             }
  371.         } else {
  372.             if (!grad->has_alpha) {
  373. #ifdef FULL_AA
  374.         if (start_alpha < 255) {
  375.                     v = r>>SHIFTIT;
  376.                     if (v < 0) v = 0;
  377.                     else if (v > 255) v = 255;
  378.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, start_alpha);
  379.                     point++;
  380.                     r += dr;
  381.             n--;
  382.         }
  383. #endif /* FULL_AA */
  384.                 while (n>0) {
  385.                     v = r>>SHIFTIT;
  386.                     if (v < 0) v = 0;
  387.                     else if (v > 255) v = 255;
  388.                     *point = (TYPE)ramp[v].pixel;
  389.                     point++;
  390.                     r += dr;
  391.             n--;
  392.                 }
  393. #ifdef FULL_AA
  394.         if (end_alpha > 0) {
  395.                     v = r>>SHIFTIT;
  396.                     if (v < 0) v = 0;
  397.                     else if (v > 255) v = 255;
  398.                     *point = mix_alpha(*point, (TYPE)ramp[v].pixel, end_alpha);
  399.         }
  400. #endif /* FULL_AA */
  401.             } else {
  402.                 while (n--) {
  403.                     v = r>>SHIFTIT;
  404.                     if (v < 0) v = 0;
  405.                     else if (v > 255) v = 255;
  406.                     cp = &ramp[v];
  407.                     *point = mix_alpha(*point, cp->pixel, cp->alpha);
  408.                     point++;
  409.                     r += dr;
  410.                 }
  411.             }
  412.         }
  413. }
  414.  
  415. ///////////// PLATFORM INDEPENDENT
  416. void
  417. GraphicDevice32::fillLineRG(Gradient *grad, long y, long start, long end)
  418. {
  419.     long X,dx,r,Y,dy;
  420.     long dist2;
  421.     register long   n;
  422.         Color *cp,*ramp;
  423.     TYPE *line;
  424.     TYPE *point;
  425.         Matrix *m = &grad->imat;
  426.         unsigned int start_alpha,end_alpha;
  427.  
  428.     if (clip(y,start,end)) return;
  429.  
  430.         start_alpha = 255 - ((start & (FRAC-1)) << (8-FRAC_BITS));
  431.         end_alpha = (end & (FRAC-1)) << (8-FRAC_BITS);
  432.  
  433.     start /= FRAC;
  434.     end /= FRAC;
  435.  
  436.     n = end-start;
  437.  
  438. #if 1
  439.         X = ((((long)m->a >> 10 ) * start + (((long)m->b) >> 10) * y) << 10) + m->tx;
  440.         Y = ((((long)m->c >> 10 ) * start + (((long)m->d) >> 10) * y) << 10) + m->ty;
  441. #else
  442.         X = (long) (m->a * start + m->b * y + m->tx);
  443.         Y = (long) (m->c * start + m->d * y + m->ty);
  444. #endif
  445.         dx = (long) (m->a);
  446.         dy = (long) (m->c);
  447.  
  448.         ramp = grad->ramp;
  449.  
  450.     line = (TYPE *)(canvasBuffer + bpl*y);
  451.     point = &line[start];
  452.  
  453.         if (!grad->has_alpha) {
  454. #ifdef FULL_AA
  455.         if (start == end) {
  456.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  457.             if ((unsigned long)dist2 >= 65536) {
  458.                 r = 255;
  459.             } else {
  460.                 r= SQRT[dist2];
  461.             }
  462.             *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha + end_alpha - 255);
  463.         } else {
  464.             if (start_alpha < 255) {
  465.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  466.             if ((unsigned long)dist2 >= 65536) {
  467.                 r = 255;
  468.             } else {
  469.                 r= SQRT[dist2];
  470.             }
  471.             *point = mix_alpha(*point, (TYPE)ramp[r].pixel, start_alpha);
  472.             point++;
  473.             X += dx;
  474.             Y += dy;
  475.             n--;
  476.             }
  477. #endif /* FULL_AA */
  478.             while (n>0) {
  479.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  480.             if ((unsigned long)dist2 >= 65536) {
  481.                 r = 255;
  482.             } else {
  483.                 r= SQRT[dist2];
  484.             }
  485.             *point = (TYPE)ramp[r].pixel;
  486.             point++;
  487.             X += dx;
  488.             Y += dy;
  489.             n--;
  490.             }
  491. #ifdef FULL_AA
  492.             if (end_alpha > 0) {
  493.             dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  494.             if ((unsigned long)dist2 >= 65536) {
  495.                 r = 255;
  496.             } else {
  497.                 r= SQRT[dist2];
  498.             }
  499.             *point = mix_alpha(*point, (TYPE)ramp[r].pixel, end_alpha);
  500.             }
  501.         }
  502. #endif /* FULL_AA */
  503.  
  504.         } else {
  505.             while (n--) {
  506.         dist2 = ((X>>16)*(X>>16))+((Y>>16)*(Y>>16));
  507.         if ((unsigned long)dist2 >= 65536) {
  508.                     r = 255;
  509.         } else {
  510.                     r= SQRT[dist2];
  511.         }
  512.                 cp = &ramp[r];
  513.         *point = mix_alpha(*point, cp->pixel, cp->alpha);
  514.         point++;
  515.         X += dx;
  516.         Y += dy;
  517.             }
  518.         }
  519. }
  520.  
  521. /* XXX: should use polygon rasterizer to handle width */
  522. /* XXX: handle only 16 bit case */
  523. /* XXX: must be clipped */
  524.  
  525. void
  526. GraphicDevice32::drawLine(long x1, long y1, long x2, long y2, long width)
  527. {
  528.     int n,adr,dx,dy,sx,color;
  529.     register int a;
  530.     register unsigned short *pp;
  531.     int alpha;
  532.  
  533. #if 0
  534.     x1 = (x1 + (FRAC/2)) >> FRAC_BITS;
  535.     y1 = (y1 + (FRAC/2)) >> FRAC_BITS;
  536.     x2 = (x2 + (FRAC/2)) >> FRAC_BITS;
  537.     y2 = (y2 + (FRAC/2)) >> FRAC_BITS;
  538. #else
  539.     x1 = (x1) >> FRAC_BITS;
  540.     y1 = (y1) >> FRAC_BITS;
  541.     x2 = (x2) >> FRAC_BITS;
  542.     y2 = (y2) >> FRAC_BITS;
  543. #endif
  544.  
  545.     if (y1 > y2 || (y1 == y2 && x1 > x2)) {
  546.         long tmp;
  547.  
  548.         tmp=x1;
  549.         x1=x2;
  550.         x2=tmp;
  551.  
  552.         tmp=y1;
  553.         y1=y2;
  554.         y2=tmp;
  555.     }
  556.  
  557.     if (y1 == y2 && (y1 < clip_rect.ymin || y1 > clip_rect.ymax)) return;
  558.     if (x1 == x2 && (x1 < clip_rect.xmin || x1 > clip_rect.xmax)) return;
  559.     if (x1 == x2 && y1 == y2) return;    // Bad !!!
  560.  
  561.     if (y1 < clip_rect.ymin && y1 != y2) {
  562.     x1 += (x2-x1)*(clip_rect.ymin-y1)/(y2-y1);
  563.     y1 = clip_rect.ymin;
  564.     }
  565.  
  566.     if (y2 > clip_rect.ymax && y1 != y2) {
  567.     x2 -= (x2-x1)*(y2-clip_rect.ymax)/(y2-y1);
  568.     y2 = clip_rect.ymax;
  569.     }
  570.  
  571.     if (x1 < x2) {
  572.         if (x1 < clip_rect.xmin && x1 != x2) {
  573.         y1 += (y2-y1)*(clip_rect.xmin-x1)/(x2-x1);
  574.         x1 = clip_rect.xmin;
  575.         }
  576.  
  577.         if (x2 > clip_rect.xmax && x1 != x2) {
  578.         y2 -= (y2-y1)*(x2-clip_rect.xmax)/(x2-x1);
  579.         x2 = clip_rect.xmax;
  580.         }
  581.     }
  582.  
  583.     if (x1 > x2) {
  584.         if (x2 < clip_rect.xmin && x2 != x1) {
  585.         y2 -= (y2-y1)*(clip_rect.xmin-x2)/(x1-x2);
  586.         x2 = clip_rect.xmin;
  587.         }
  588.  
  589.         if (x1 > clip_rect.xmax && x2 != x1) {
  590.         y1 += (y2-y1)*(x1-clip_rect.xmax)/(x1-x2);
  591.         x1 = clip_rect.xmax;
  592.         }
  593.     }
  594.  
  595.     // Check again
  596.     if (x1 == x2 && y1 == y2) return;
  597.     if (x1 < clip_rect.xmin || x2 < clip_rect.xmin) return;
  598.     if (y1 < clip_rect.ymin || y2 < clip_rect.ymin) return;
  599.     if (x1 > clip_rect.xmax || x2 > clip_rect.xmax) return;
  600.     if (y1 > clip_rect.ymax || y2 > clip_rect.ymax) return;
  601.  
  602.     sx=bpl >> 1;
  603.     adr=(y1 * sx + x1);
  604.     pp = (unsigned short *)canvasBuffer + adr;
  605.  
  606.     dx = x2 - x1;
  607.     dy = y2 - y1;
  608.  
  609. #if defined(RISCOS)
  610.     color = allocColor(foregroundColor);
  611. #else
  612.     color = allocColor16_565(foregroundColor);
  613. #endif
  614.     alpha = foregroundColor.alpha;
  615.  
  616.     if (alpha == ALPHA_OPAQUE) {
  617.  
  618. #define PUTPIXEL()                 \
  619.   {                        \
  620.       *pp=color;                        \
  621.   }
  622.  
  623. #define DRAWLINE(dx,dy,inc_1,inc_2) \
  624.     n=dx;\
  625.     a=2*dy-dx;\
  626.     dy=2*dy;\
  627.     dx=2*dx-dy;\
  628.      do {\
  629.       PUTPIXEL();\
  630.             if (a>0) { pp+=(inc_1); a-=dx; }\
  631.             else { pp+=(inc_2); a+=dy; }\
  632.      } while (--n >= 0);
  633.  
  634. /* fin macro */
  635.  
  636.   if (dx == 0 && dy == 0) {
  637.     PUTPIXEL();
  638.   } else if (dx > 0) {
  639.     if (dx >= dy) {
  640.       DRAWLINE(dx, dy, sx + 1, 1);
  641.     } else {
  642.       DRAWLINE(dy, dx, sx + 1, sx);
  643.     }
  644.   } else {
  645.     dx = -dx;
  646.     if (dx >= dy) {
  647.       DRAWLINE(dx, dy, sx - 1, -1);
  648.     } else {
  649.       DRAWLINE(dy, dx, sx - 1, sx);
  650.     }
  651.   }
  652.  
  653.  
  654. #undef DRAWLINE
  655. #undef PUTPIXEL
  656.     } else {
  657. #define PUTPIXEL()                 \
  658.   {                        \
  659.       *pp=mix_alpha(*pp,color,alpha);            \
  660.   }
  661.  
  662. #define DRAWLINE(dx,dy,inc_1,inc_2) \
  663.     n=dx;\
  664.     a=2*dy-dx;\
  665.     dy=2*dy;\
  666.     dx=2*dx-dy;\
  667.      do {\
  668.       PUTPIXEL();\
  669.             if (a>0) { pp+=(inc_1); a-=dx; }\
  670.             else { pp+=(inc_2); a+=dy; }\
  671.      } while (--n >= 0);
  672.  
  673. /* fin macro */
  674.  
  675.   if (dx == 0 && dy == 0) {
  676.     PUTPIXEL();
  677.   } else if (dx > 0) {
  678.     if (dx >= dy) {
  679.       DRAWLINE(dx, dy, sx + 1, 1);
  680.     } else {
  681.       DRAWLINE(dy, dx, sx + 1, sx);
  682.     }
  683.   } else {
  684.     dx = -dx;
  685.     if (dx >= dy) {
  686.       DRAWLINE(dx, dy, sx - 1, -1);
  687.     } else {
  688.       DRAWLINE(dy, dx, sx - 1, sx);
  689.     }
  690.   }
  691.  
  692.  
  693. #undef DRAWLINE
  694. #undef PUTPIXEL
  695.     }
  696. }
  697.  
  698.