LCOV - code coverage report
Current view: top level - addons/primitives - high_primitives.c (source / functions) Hit Total Coverage
Test: allegro_auto.info Lines: 513 645 79.5 %
Date: 2013-01-02 Functions: 20 21 95.2 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 156 328 47.6 %

           Branch data     Line data    Source code
       1                 :            : /*         ______   ___    ___
       2                 :            :  *        /\  _  \ /\_ \  /\_ \
       3                 :            :  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
       4                 :            :  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
       5                 :            :  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
       6                 :            :  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
       7                 :            :  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
       8                 :            :  *                                           /\____/
       9                 :            :  *                                           \_/__/
      10                 :            :  *
      11                 :            :  *      Some high level routines, provided for user's convinience.
      12                 :            :  *
      13                 :            :  *
      14                 :            :  *      By Pavel Sountsov.
      15                 :            :  *
      16                 :            :  *
      17                 :            :  *      Bezier spline plotter By Seymour Shlien.
      18                 :            :  *
      19                 :            :  *      Optimised version by Sven Sandberg.
      20                 :            :  *
      21                 :            :  *      I'm not sure wether or not we still use the Castelau Algorithm
      22                 :            :  *      described in the book :o)
      23                 :            :  *
      24                 :            :  *      Interactive Computer Graphics
      25                 :            :  *      by Peter Burger and Duncan Gillies
      26                 :            :  *      Addison-Wesley Publishing Co 1989
      27                 :            :  *      ISBN 0-201-17439-1
      28                 :            :  *
      29                 :            :  *      The 4 th order Bezier curve is a cubic curve passing
      30                 :            :  *      through the first and fourth point. The curve does
      31                 :            :  *      not pass through the middle two points. They are merely
      32                 :            :  *      guide points which control the shape of the curve. The
      33                 :            :  *      curve is tangent to the lines joining points 1 and 2
      34                 :            :  *      and points 3 and 4.
      35                 :            :  *
      36                 :            :  *      See readme.txt for copyright information.
      37                 :            :  */
      38                 :            : 
      39                 :            : 
      40                 :            : #include "allegro5/allegro_primitives.h"
      41                 :            : #ifdef ALLEGRO_CFG_OPENGL
      42                 :            : #include "allegro5/allegro_opengl.h"
      43                 :            : #endif
      44                 :            : #include "allegro5/internal/aintern_bitmap.h"
      45                 :            : #include <math.h>
      46                 :            : 
      47                 :            : #ifdef ALLEGRO_MSVC
      48                 :            :    #define hypotf(x, y) _hypotf((x), (y))
      49                 :            : #endif
      50                 :            : 
      51                 :            : #define LOCAL_VERTEX_CACHE  ALLEGRO_VERTEX vertex_cache[ALLEGRO_VERTEX_CACHE_SIZE]
      52                 :            : 
      53                 :            : /*
      54                 :            :  * Make an estimate of the scale of the current transformation. 
      55                 :            :  */
      56                 :        124 : static float get_scale(void)
      57                 :            : {
      58                 :        124 :    const ALLEGRO_TRANSFORM* t = al_get_current_transform();
      59                 :        124 :    return (hypotf(t->m[0][0], t->m[0][1]) + hypotf(t->m[1][0], t->m[1][1])) / 2;
      60                 :            : }
      61                 :            : 
      62                 :            : /* Function: al_draw_line
      63                 :            :  */
      64                 :       4144 : void al_draw_line(float x1, float y1, float x2, float y2,
      65                 :            :    ALLEGRO_COLOR color, float thickness)
      66                 :            : {
      67         [ +  + ]:       4144 :    if (thickness > 0) {
      68                 :            :       int ii;
      69                 :            :       float tx, ty;
      70                 :         34 :       float len = hypotf(x2 - x1, y2 - y1);
      71                 :            :       
      72                 :            :       ALLEGRO_VERTEX vtx[4];
      73                 :            : 
      74         [ +  - ]:         34 :       if (len == 0)
      75                 :       4144 :          return;
      76                 :            : 
      77                 :         34 :       tx = 0.5f * thickness * (y2 - y1) / len;
      78                 :         34 :       ty = 0.5f * thickness * -(x2 - x1) / len;
      79                 :            :             
      80                 :         34 :       vtx[0].x = x1 + tx; vtx[0].y = y1 + ty;
      81                 :         34 :       vtx[1].x = x1 - tx; vtx[1].y =  y1 - ty;
      82                 :         34 :       vtx[2].x = x2 - tx; vtx[2].y = y2 - ty;
      83                 :         34 :       vtx[3].x = x2 + tx; vtx[3].y = y2 + ty;
      84                 :            :       
      85         [ +  + ]:        170 :       for (ii = 0; ii < 4; ii++) {
      86                 :        136 :          vtx[ii].color = color;
      87                 :        136 :          vtx[ii].z = 0;
      88                 :            :       }
      89                 :            :       
      90                 :         34 :       al_draw_prim(vtx, 0, 0, 0, 4, ALLEGRO_PRIM_TRIANGLE_FAN);
      91                 :            :       
      92                 :            :    } else {
      93                 :            :       ALLEGRO_VERTEX vtx[2];
      94                 :            :          
      95                 :       4110 :       vtx[0].x = x1; vtx[0].y = y1;
      96                 :       4110 :       vtx[1].x = x2; vtx[1].y = y2;
      97                 :            :       
      98                 :       4110 :       vtx[0].color = color;
      99                 :       4110 :       vtx[1].color = color;
     100                 :       4110 :       vtx[0].z = 0;
     101                 :       4110 :       vtx[1].z = 0;
     102                 :            :       
     103                 :       4110 :       al_draw_prim(vtx, 0, 0, 0, 2, ALLEGRO_PRIM_LINE_LIST);
     104                 :            :    }
     105                 :            : }
     106                 :            : 
     107                 :            : /* Function: al_draw_triangle
     108                 :            :  */
     109                 :         16 : void al_draw_triangle(float x1, float y1, float x2, float y2,
     110                 :            :    float x3, float y3, ALLEGRO_COLOR color, float thickness)
     111                 :            : {
     112         [ +  + ]:         16 :    if (thickness > 0) {
     113                 :         14 :       int ii = 0;
     114                 :            :       float side1, side2, side3;      
     115                 :            :       float perimeter, semi_perimeter;
     116                 :            :       float outer_frac, inner_frac;
     117                 :            :       float incenter_x, incenter_y;
     118                 :            :       float incircle_rad;
     119                 :         14 :       int idx = 0;
     120                 :            :       ALLEGRO_VERTEX vtx[5];
     121                 :         14 :       float x[3] = {x1, x2, x3};
     122                 :         14 :       float y[3] = {y1, y2, y3};
     123                 :            :       ALLEGRO_VERTEX first_inner_vtx;
     124                 :            :       ALLEGRO_VERTEX first_outer_vtx;
     125                 :            :       ALLEGRO_VERTEX ini_vtx;
     126                 :         14 :       float cross = (x[1] - x[0]) * (y[2] - y[0]) - (x[2] - x[0]) * (y[1] - y[0]);
     127                 :            :       
     128                 :         14 :       ini_vtx.x = ini_vtx.y = ini_vtx.z = ini_vtx.u = ini_vtx.v = 0;
     129                 :         14 :       ini_vtx.color = color;
     130                 :         14 :       first_inner_vtx = ini_vtx;
     131                 :         14 :       first_outer_vtx = ini_vtx;
     132                 :            :       
     133                 :            :       /*
     134                 :            :        * If the triangle is very flat, draw it as a line
     135                 :            :        */
     136         [ -  + ]:         14 :       if(fabs(cross) < 0.0001f) {
     137                 :            :          float tx, ty, lx, ly;
     138                 :            :          float len;
     139                 :            :          /*
     140                 :            :           * Find the obtuse vertex via two dot products
     141                 :            :           */
     142                 :          0 :          float dot = (x[1] - x[0]) * (x[2] - x[0]) + (y[1] - y[0]) * (y[2] - y[0]);
     143         [ #  # ]:          0 :          if(dot < 0) {
     144                 :            :             x1 = x[1]; y1 = y[1];
     145                 :            :             x2 = x[2]; y2 = y[2];
     146                 :            :          } else {
     147                 :          0 :             dot = (x[0] - x[1]) * (x[2] - x[1]) + (y[0] - y[1]) * (y[2] - y[1]);
     148         [ #  # ]:          0 :             if(dot < 0) {
     149                 :            :                x1 = x[0]; y1 = y[0];
     150                 :            :                x2 = x[2]; y2 = y[2];
     151                 :            :             } else {
     152                 :          0 :                x1 = x[0]; y1 = y[0];
     153                 :          0 :                x2 = x[1]; y2 = y[1];
     154                 :            :             }
     155                 :            :          }
     156                 :          0 :          len = hypotf(x2 - x1, y2 - y1);
     157                 :            : 
     158         [ #  # ]:          0 :          if (len == 0)
     159                 :            :             return;
     160                 :            : 
     161                 :          0 :          tx = 0.5f * thickness * (y2 - y1) / len;
     162                 :          0 :          ty = 0.5f * thickness * -(x2 - x1) / len;
     163                 :          0 :          lx = 0.5f * thickness * (x2 - x1) / len;
     164                 :          0 :          ly = 0.5f * thickness * (y2 - y1) / len;
     165                 :            :                
     166                 :          0 :          vtx[0].x = x1 + tx - lx; vtx[0].y = y1 + ty - ly;
     167                 :          0 :          vtx[1].x = x1 - tx - lx; vtx[1].y = y1 - ty - ly;
     168                 :          0 :          vtx[2].x = x2 - tx + lx; vtx[2].y = y2 - ty + ly;
     169                 :          0 :          vtx[3].x = x2 + tx + lx; vtx[3].y = y2 + ty + ly;
     170                 :            :          
     171         [ #  # ]:          0 :          for (ii = 0; ii < 4; ii++) {
     172                 :          0 :             vtx[ii].color = color;
     173                 :          0 :             vtx[ii].z = 0;
     174                 :            :          }
     175                 :            :          
     176                 :          0 :          al_draw_prim(vtx, 0, 0, 0, 4, ALLEGRO_PRIM_TRIANGLE_FAN);
     177                 :            :          return;
     178                 :            :       }
     179         [ -  + ]:         14 :       else if(cross > 0) {
     180                 :            :          /*
     181                 :            :           * Points need to be wound correctly for the algorithm to work
     182                 :            :           */
     183                 :            :          float t;
     184                 :          0 :          t = x[1];
     185                 :          0 :          x[1] = x[2];
     186                 :          0 :          x[2] = t;
     187                 :            :          
     188                 :          0 :          t = y[1];
     189                 :          0 :          y[1] = y[2];
     190                 :          0 :          y[2] = t;
     191                 :            :       }
     192                 :            :   
     193                 :         14 :       side1 = hypotf(x[1] - x[0], y[1] - y[0]);
     194                 :         14 :       side2 = hypotf(x[2] - x[0], y[2] - y[0]);
     195                 :         14 :       side3 = hypotf(x[2] - x[1], y[2] - y[1]);
     196                 :            : 
     197                 :         14 :       perimeter = side1 + side2 + side3;
     198                 :         14 :       semi_perimeter = perimeter / 2.0f;
     199         [ +  - ]:         14 :       if (semi_perimeter < 0.00001f)
     200                 :            :          return;
     201                 :            : 
     202                 :         14 :       incircle_rad = sqrtf((semi_perimeter - side1) * (semi_perimeter - side2) * (semi_perimeter - side3) / semi_perimeter);
     203                 :            : 
     204         [ +  - ]:         14 :       if (incircle_rad < 0.00001f)
     205                 :            :          return;
     206                 :            : 
     207                 :         14 :       outer_frac = (incircle_rad + thickness / 2) / incircle_rad;
     208                 :         14 :       inner_frac = (incircle_rad - thickness / 2) / incircle_rad;
     209                 :            :       
     210         [ -  + ]:         14 :       if(inner_frac < 0)
     211                 :          0 :          inner_frac = 0;
     212                 :            : 
     213                 :         14 :       incenter_x = (side1 * x[2] + side2 * x[1] + side3 * x[0]) / perimeter;
     214                 :         14 :       incenter_y = (side1 * y[2] + side2 * y[1] + side3 * y[0]) / perimeter;
     215                 :            : 
     216                 :            :       #define DRAW                                                         \
     217                 :            :             if(ii != 0) {                                                  \
     218                 :            :                vtx[idx++] = outer_vtx;                                     \
     219                 :            :                vtx[idx++] = inner_vtx;                                     \
     220                 :            :                                                                            \
     221                 :            :                al_draw_prim(vtx, 0, 0, 0, idx, ALLEGRO_PRIM_TRIANGLE_FAN); \
     222                 :            :                                                                            \
     223                 :            :                idx = 0;                                                    \
     224                 :            :             }
     225                 :            : 
     226                 :            :       /*
     227                 :            :        * Iterate across the vertices, and draw each side of the triangle separately
     228                 :            :        */
     229         [ +  + ]:         56 :       for(ii = 0; ii < 3; ii++)
     230                 :            :       {
     231                 :         42 :          float vert_x = x[ii] - incenter_x;
     232                 :         42 :          float vert_y = y[ii] - incenter_y;
     233                 :            :          
     234                 :         42 :          float o_dx = vert_x * outer_frac;
     235                 :         42 :          float o_dy = vert_y * outer_frac;
     236                 :            :          
     237                 :         42 :          float i_dx = vert_x * inner_frac;
     238                 :         42 :          float i_dy = vert_y * inner_frac;
     239                 :            :          
     240                 :         42 :          float tdx = o_dx - i_dx;
     241                 :         42 :          float tdy = o_dy - i_dy;
     242                 :            :          
     243                 :         42 :          ALLEGRO_VERTEX inner_vtx = ini_vtx;
     244                 :         42 :          ALLEGRO_VERTEX outer_vtx = ini_vtx;
     245                 :            :          
     246         [ -  + ]:         42 :          if(tdx * tdx + tdy * tdy > 16 * thickness * thickness) {
     247                 :          0 :             float x_pos = x[(ii + 1) % 3];
     248                 :          0 :             float y_pos = y[(ii + 1) % 3];
     249                 :            :             
     250                 :          0 :             float x_neg = x[(ii + 2) % 3];
     251                 :          0 :             float y_neg = y[(ii + 2) % 3];
     252                 :            :             
     253                 :          0 :             float x1_x2 = x[ii] - x_pos;
     254                 :          0 :             float y1_y2 = y[ii] - y_pos;
     255                 :            :             
     256                 :          0 :             float x1_x3 = x[ii] - x_neg;
     257                 :          0 :             float y1_y3 = y[ii] - y_neg;
     258                 :            :             
     259                 :          0 :             float mag_1_2 = hypotf(x1_x2, y1_y2);
     260                 :          0 :             float mag_1_3 = hypotf(x1_x3, y1_y3);
     261                 :            :             
     262                 :          0 :             ALLEGRO_VERTEX next_vtx = ini_vtx;
     263                 :            :             
     264                 :          0 :             x1_x2 *= thickness / 2 / mag_1_2;
     265                 :          0 :             y1_y2 *= thickness / 2 / mag_1_2;
     266                 :            :             
     267                 :          0 :             x1_x3 *= thickness / 2 / mag_1_3;
     268                 :          0 :             y1_y3 *= thickness / 2 / mag_1_3;
     269                 :            :             
     270                 :          0 :             outer_vtx.x = x[ii] + x1_x3 - y1_y3; outer_vtx.y = y[ii] + y1_y3 + x1_x3;
     271                 :          0 :             inner_vtx.x = incenter_x + i_dx; inner_vtx.y = incenter_y + i_dy;
     272                 :          0 :             next_vtx.x = x[ii] + x1_x2 + y1_y2; next_vtx.y = y[ii] + y1_y2 - x1_x2;
     273                 :            :             
     274         [ #  # ]:          0 :             DRAW
     275                 :            :             
     276                 :          0 :             vtx[idx++] = inner_vtx;
     277                 :          0 :             vtx[idx++] = outer_vtx;
     278                 :          0 :             vtx[idx++] = next_vtx;
     279                 :            :          } else {
     280                 :         42 :             inner_vtx.x = incenter_x + i_dx; inner_vtx.y = incenter_y + i_dy;
     281                 :         42 :             outer_vtx.x = incenter_x + o_dx; outer_vtx.y = incenter_y + o_dy;
     282                 :            :             
     283         [ +  + ]:         42 :             DRAW
     284                 :            :             
     285                 :         42 :             vtx[idx++] = inner_vtx;
     286                 :         42 :             vtx[idx++] = outer_vtx;
     287                 :            :          }
     288                 :            :          
     289         [ +  + ]:         42 :          if(ii == 0) {
     290                 :         14 :             first_inner_vtx = inner_vtx;
     291                 :         14 :             first_outer_vtx = outer_vtx;
     292                 :            :          }
     293                 :            :       }
     294                 :            :       
     295                 :         14 :       vtx[idx++] = first_outer_vtx;
     296                 :         14 :       vtx[idx++] = first_inner_vtx;
     297                 :            : 
     298                 :         14 :       al_draw_prim(vtx, 0, 0, 0, idx, ALLEGRO_PRIM_TRIANGLE_FAN);
     299                 :            :       
     300                 :            :       #undef DRAW
     301                 :            :    } else {
     302                 :            :       ALLEGRO_VERTEX vtx[3];
     303                 :            :          
     304                 :          2 :       vtx[0].x = x1; vtx[0].y = y1;
     305                 :          2 :       vtx[1].x = x2; vtx[1].y = y2;
     306                 :          2 :       vtx[2].x = x3; vtx[2].y = y3;
     307                 :            :       
     308                 :          2 :       vtx[0].color = color;
     309                 :          2 :       vtx[1].color = color;
     310                 :          2 :       vtx[2].color = color;
     311                 :            :       
     312                 :          2 :       vtx[0].z = 0;
     313                 :          2 :       vtx[1].z = 0;
     314                 :          2 :       vtx[2].z = 0;
     315                 :            :       
     316                 :         16 :       al_draw_prim(vtx, 0, 0, 0, 3, ALLEGRO_PRIM_LINE_LOOP);
     317                 :            :    }
     318                 :            : }
     319                 :            : 
     320                 :            : /* Function: al_draw_filled_triangle
     321                 :            :  */
     322                 :         10 : void al_draw_filled_triangle(float x1, float y1, float x2, float y2,
     323                 :            :    float x3, float y3, ALLEGRO_COLOR color)
     324                 :            : {
     325                 :            :    ALLEGRO_VERTEX vtx[3];
     326                 :            : 
     327                 :         10 :    vtx[0].x = x1; vtx[0].y = y1;
     328                 :         10 :    vtx[1].x = x2; vtx[1].y = y2;
     329                 :         10 :    vtx[2].x = x3; vtx[2].y = y3;
     330                 :            :   
     331                 :         10 :    vtx[0].color = color;
     332                 :         10 :    vtx[1].color = color;
     333                 :         10 :    vtx[2].color = color;
     334                 :            :    
     335                 :         10 :    vtx[0].z = 0;
     336                 :         10 :    vtx[1].z = 0;
     337                 :         10 :    vtx[2].z = 0;
     338                 :            :    
     339                 :         10 :    al_draw_prim(vtx, 0, 0, 0, 3, ALLEGRO_PRIM_TRIANGLE_LIST);
     340                 :         10 : }
     341                 :            : 
     342                 :            : /* Function: al_draw_rectangle
     343                 :            :  */
     344                 :         46 : void al_draw_rectangle(float x1, float y1, float x2, float y2,
     345                 :            :    ALLEGRO_COLOR color, float thickness)
     346                 :            : {
     347                 :            :    int ii;
     348                 :            : 
     349         [ +  + ]:         46 :    if (thickness > 0) {
     350                 :         38 :       float t = thickness / 2;
     351                 :            :       ALLEGRO_VERTEX vtx[10];
     352                 :            :                
     353                 :         38 :       vtx[0].x = x1 - t; vtx[0].y = y1 - t;
     354                 :         38 :       vtx[1].x = x1 + t; vtx[1].y = y1 + t;
     355                 :         38 :       vtx[2].x = x2 + t; vtx[2].y = y1 - t;
     356                 :         38 :       vtx[3].x = x2 - t; vtx[3].y = y1 + t;
     357                 :         38 :       vtx[4].x = x2 + t; vtx[4].y = y2 + t;
     358                 :         38 :       vtx[5].x = x2 - t; vtx[5].y = y2 - t;
     359                 :         38 :       vtx[6].x = x1 - t; vtx[6].y = y2 + t;
     360                 :         38 :       vtx[7].x = x1 + t; vtx[7].y = y2 - t;
     361                 :         38 :       vtx[8].x = x1 - t; vtx[8].y = y1 - t;
     362                 :         38 :       vtx[9].x = x1 + t; vtx[9].y = y1 + t;
     363                 :            :       
     364         [ +  + ]:        418 :       for (ii = 0; ii < 10; ii++) {
     365                 :        380 :          vtx[ii].color = color;
     366                 :        380 :          vtx[ii].z = 0;
     367                 :            :       }
     368                 :            :       
     369                 :         38 :       al_draw_prim(vtx, 0, 0, 0, 10, ALLEGRO_PRIM_TRIANGLE_STRIP);
     370                 :            :    } else {
     371                 :            :       ALLEGRO_VERTEX vtx[4];
     372                 :            :          
     373                 :          8 :       vtx[0].x = x1; vtx[0].y = y1;
     374                 :          8 :       vtx[1].x = x2; vtx[1].y = y1;
     375                 :          8 :       vtx[2].x = x2; vtx[2].y = y2;
     376                 :          8 :       vtx[3].x = x1; vtx[3].y = y2;
     377                 :            :       
     378         [ +  + ]:         40 :       for (ii = 0; ii < 4; ii++) {
     379                 :         32 :          vtx[ii].color = color;
     380                 :         32 :          vtx[ii].z = 0;
     381                 :            :       }
     382                 :            :       
     383                 :          8 :       al_draw_prim(vtx, 0, 0, 0, 4, ALLEGRO_PRIM_LINE_LOOP);
     384                 :            :    }
     385                 :         46 : }
     386                 :            : 
     387                 :            : /* Function: al_draw_filled_rectangle
     388                 :            :  */
     389                 :         24 : void al_draw_filled_rectangle(float x1, float y1, float x2, float y2,
     390                 :            :    ALLEGRO_COLOR color)
     391                 :            : {
     392                 :            :    ALLEGRO_VERTEX vtx[4];
     393                 :            :    int ii;
     394                 :            : 
     395                 :         24 :    vtx[0].x = x1; vtx[0].y = y1;
     396                 :         24 :    vtx[1].x = x1; vtx[1].y = y2;
     397                 :         24 :    vtx[2].x = x2; vtx[2].y = y2;
     398                 :         24 :    vtx[3].x = x2; vtx[3].y = y1;
     399                 :            :    
     400         [ +  + ]:        120 :    for (ii = 0; ii < 4; ii++) {
     401                 :         96 :       vtx[ii].color = color;
     402                 :         96 :       vtx[ii].z = 0;
     403                 :            :    }
     404                 :            :    
     405                 :         24 :    al_draw_prim(vtx, 0, 0, 0, 4, ALLEGRO_PRIM_TRIANGLE_FAN);
     406                 :         24 : }
     407                 :            : 
     408                 :            : /* Function: al_calculate_arc
     409                 :            :  */
     410                 :        102 : void al_calculate_arc(float* dest, int stride, float cx, float cy,
     411                 :            :    float rx, float ry, float start_theta, float delta_theta, float thickness,
     412                 :            :    int num_segments)
     413                 :            : {   
     414                 :            :    float theta;
     415                 :            :    float c;
     416                 :            :    float s;
     417                 :            :    float x, y, t;
     418                 :            :    int ii;
     419                 :            :  
     420 [ -  + ][ #  # ]:        102 :    ASSERT(dest);
                 [ #  # ]
     421 [ -  + ][ #  # ]:        102 :    ASSERT(num_segments > 1);
                 [ #  # ]
     422 [ -  + ][ #  # ]:        102 :    ASSERT(rx >= 0);
                 [ #  # ]
     423 [ -  + ][ #  # ]:        102 :    ASSERT(ry >= 0);
                 [ #  # ]
     424                 :            : 
     425         [ +  + ]:        102 :    if (thickness > 0.0f) {
     426                 :         62 :       theta = delta_theta / ((float)(num_segments) - 1);
     427                 :         62 :       c = cosf(theta);
     428                 :         62 :       s = sinf(theta);
     429                 :         62 :       x = cosf(start_theta);
     430                 :         62 :       y = sinf(start_theta);
     431                 :            :  
     432         [ +  + ]:         62 :       if (rx == ry) {
     433                 :            :          /*
     434                 :            :          The circle case is particularly simple
     435                 :            :          */
     436                 :         24 :          float r1 = rx - thickness / 2.0f;
     437                 :         24 :          float r2 = rx + thickness / 2.0f;
     438         [ +  + ]:       1600 :          for (ii = 0; ii < num_segments; ii ++) {
     439                 :       1576 :             *dest =       r2 * x + cx;
     440                 :       1576 :             *(dest + 1) = r2 * y + cy;
     441                 :       1576 :             dest = (float*)(((char*)dest) + stride);
     442                 :       1576 :             *dest =        r1 * x + cx;
     443                 :       1576 :             *(dest + 1) =  r1 * y + cy;
     444                 :       1576 :             dest = (float*)(((char*)dest) + stride);
     445                 :            :             
     446                 :       1576 :             t = x;
     447                 :       1576 :             x = c * x - s * y;
     448                 :       1576 :             y = s * t + c * y;
     449                 :            :          }
     450                 :            :       } else {
     451         [ +  - ]:         38 :          if (rx != 0 && !ry == 0) {
     452         [ +  + ]:       2450 :             for (ii = 0; ii < num_segments; ii++) {
     453                 :       2412 :                float denom = hypotf(ry * x, rx * y);
     454                 :       2412 :                float nx = thickness / 2 * ry * x / denom;
     455                 :       2412 :                float ny = thickness / 2 * rx * y / denom;
     456                 :            : 
     457                 :       2412 :                *dest =       rx * x + cx + nx;
     458                 :       2412 :                *(dest + 1) = ry * y + cy + ny;
     459                 :       2412 :                dest = (float*)(((char*)dest) + stride);
     460                 :       2412 :                *dest =       rx * x + cx - nx;
     461                 :       2412 :                *(dest + 1) = ry * y + cy - ny;
     462                 :       2412 :                dest = (float*)(((char*)dest) + stride);
     463                 :            : 
     464                 :       2412 :                t = x;
     465                 :       2412 :                x = c * x - s * y;
     466                 :       2412 :                y = s * t + c * y;
     467                 :            :             }
     468                 :            :          }
     469                 :            :       }
     470                 :            :    } else {
     471                 :         40 :       theta = delta_theta / ((float)num_segments - 1);
     472                 :         40 :       c = cosf(theta);
     473                 :         40 :       s = sinf(theta);
     474                 :         40 :       x = cosf(start_theta);
     475                 :         40 :       y = sinf(start_theta);
     476                 :            :       
     477         [ +  + ]:       1886 :       for (ii = 0; ii < num_segments; ii++) {
     478                 :       1846 :          *dest =       rx * x + cx;
     479                 :       1846 :          *(dest + 1) = ry * y + cy;
     480                 :       1846 :          dest = (float*)(((char*)dest) + stride);
     481                 :            : 
     482                 :       1846 :          t = x;
     483                 :       1846 :          x = c * x - s * y;
     484                 :       1846 :          y = s * t + c * y;
     485                 :            :       }
     486                 :            :    }
     487                 :        102 : }
     488                 :            : 
     489                 :            : /* Function: al_draw_pieslice
     490                 :            :  */
     491                 :          4 : void al_draw_pieslice(float cx, float cy, float r, float start_theta,
     492                 :            :    float delta_theta, ALLEGRO_COLOR color, float thickness)
     493                 :            : {
     494                 :            :    LOCAL_VERTEX_CACHE;
     495                 :          4 :    float scale = get_scale();
     496                 :            :    int num_segments, ii;
     497                 :            :    
     498 [ -  + ][ #  # ]:          4 :    ASSERT(r >= 0);
                 [ #  # ]
     499                 :            :    
     500                 :            :    /* Just makes things a bit easier */
     501         [ -  + ]:          4 :    if(delta_theta < 0) {
     502                 :          0 :       delta_theta = -delta_theta;
     503                 :          0 :       start_theta -= delta_theta;
     504                 :            :    }
     505                 :            :    
     506         [ -  + ]:          4 :    if (thickness <= 0) {
     507                 :          0 :       num_segments = fabs(delta_theta / (2 * ALLEGRO_PI) * ALLEGRO_PRIM_QUALITY * scale * sqrtf(r));
     508                 :            : 
     509         [ #  # ]:          0 :       if (num_segments < 2)
     510                 :          0 :          num_segments = 2;
     511                 :            :       
     512         [ #  # ]:          0 :       if (num_segments + 1 >= ALLEGRO_VERTEX_CACHE_SIZE) {
     513                 :          0 :          num_segments = ALLEGRO_VERTEX_CACHE_SIZE - 1 - 1;
     514                 :            :       }
     515                 :            :          
     516                 :          0 :       al_calculate_arc(&(vertex_cache[1].x), sizeof(ALLEGRO_VERTEX), cx, cy, r, r, start_theta, delta_theta, 0, num_segments);
     517                 :          0 :       vertex_cache[0].x = cx; vertex_cache[0].y = cy;
     518                 :            :       
     519         [ #  # ]:          0 :       for (ii = 0; ii < num_segments + 1; ii++) {
     520                 :          0 :          vertex_cache[ii].color = color;
     521                 :          0 :          vertex_cache[ii].z = 0;
     522                 :            :       }
     523                 :            :       
     524                 :          0 :       al_draw_prim(vertex_cache, 0, 0, 0, num_segments + 1, ALLEGRO_PRIM_LINE_LOOP);
     525                 :            :    } else {
     526                 :          4 :       float ht = thickness / 2;
     527                 :          4 :       float inner_side_angle = asinf(ht / (r - ht));
     528                 :          4 :       float outer_side_angle = asinf(ht / (r + ht));
     529                 :          4 :       float central_angle = delta_theta - 2 * inner_side_angle;
     530                 :          4 :       bool inverted_winding = ((int)(delta_theta / ALLEGRO_PI)) % 2 == 1;
     531                 :          4 :       float midangle = start_theta + (fmodf(delta_theta + ALLEGRO_PI, 2 * ALLEGRO_PI) - ALLEGRO_PI) / 2;
     532                 :          4 :       float midpoint_dir_x = cosf(midangle);
     533                 :          4 :       float midpoint_dir_y = sinf(midangle);
     534                 :          4 :       float side_dir_x = cosf(start_theta);
     535                 :          4 :       float side_dir_y = sinf(start_theta);
     536                 :          4 :       float sine_half_delta = fabs(side_dir_x * midpoint_dir_y - side_dir_y * midpoint_dir_x); /* Cross product */
     537                 :          4 :       float connect_len = ht / sine_half_delta;
     538                 :          4 :       bool blunt_tip = connect_len > 2 * thickness;
     539                 :            :       
     540                 :            :       /* The angle is big enough for there to be a hole in the middle */
     541         [ +  - ]:          4 :       if (central_angle > 0) {
     542                 :          4 :          float central_start_angle = start_theta + inner_side_angle;
     543                 :            :          size_t vtx_id;
     544                 :            :          int vtx_delta;
     545                 :            :          /* Two inner hole vertices and the apex (2 vertices if the apex is blunt) */
     546         [ -  + ]:          4 :          int extra_vtx = blunt_tip ? 4 : 3;
     547                 :            :          
     548                 :          4 :          al_draw_arc(cx, cy, r, central_start_angle, central_angle, color, thickness);
     549                 :            :          
     550                 :          4 :          vertex_cache[0].x = cx + (r - thickness / 2) * cosf(central_start_angle);
     551                 :          4 :          vertex_cache[0].y = cy + (r - thickness / 2) * sinf(central_start_angle);
     552                 :            :          
     553                 :          4 :          num_segments = (inner_side_angle + outer_side_angle) / (2 * ALLEGRO_PI) * ALLEGRO_PRIM_QUALITY * scale * sqrtf(r + ht);
     554                 :            :          
     555         [ +  - ]:          4 :          if (num_segments < 2)
     556                 :          4 :             num_segments = 2;
     557                 :            :          
     558         [ -  + ]:          4 :          if (num_segments + extra_vtx >= ALLEGRO_VERTEX_CACHE_SIZE)
     559                 :          0 :             num_segments = ALLEGRO_VERTEX_CACHE_SIZE - 1 - extra_vtx;
     560                 :            :            
     561                 :          4 :          al_calculate_arc(&(vertex_cache[1].x), sizeof(ALLEGRO_VERTEX), cx, cy, r + ht, r + ht, central_start_angle, -(outer_side_angle + inner_side_angle), 0, num_segments);
     562                 :            :          
     563                 :            :          /* Do the tip */
     564         [ +  - ]:          4 :          vtx_id = num_segments + 1 + (inverted_winding ? (1 + (blunt_tip ? 1 : 0)) : 0);
     565         [ -  + ]:          4 :          vtx_delta = inverted_winding ? -1 : 1;
     566         [ +  - ]:          4 :          if (blunt_tip) {
     567         [ -  + ]:          4 :             float vx = ht * (side_dir_y * (inverted_winding ? -1 : 1) - side_dir_x);
     568         [ -  + ]:          4 :             float vy = ht * (-side_dir_x * (inverted_winding ? -1 : 1) - side_dir_y);
     569                 :          4 :             float dot = vx * midpoint_dir_x + vy * midpoint_dir_y;
     570                 :            :             
     571                 :          4 :             vertex_cache[vtx_id].x = cx + vx;
     572                 :          4 :             vertex_cache[vtx_id].y = cy + vy;
     573                 :          4 :             vtx_id += vtx_delta;
     574                 :            :             
     575                 :          4 :             vertex_cache[vtx_id].x = cx + dot * midpoint_dir_x;
     576                 :          4 :             vertex_cache[vtx_id].y = cy + dot * midpoint_dir_y;
     577                 :            :          } else {
     578                 :          0 :             vertex_cache[vtx_id].x = cx - connect_len * midpoint_dir_x;
     579                 :          0 :             vertex_cache[vtx_id].y = cy - connect_len * midpoint_dir_y;
     580                 :            :          }
     581                 :          4 :          vtx_id += vtx_delta;
     582                 :            :          
     583         [ -  + ]:          4 :          if(connect_len > r - ht)
     584                 :          0 :             connect_len = r - ht;
     585                 :          4 :          vertex_cache[vtx_id].x = cx + connect_len * midpoint_dir_x;
     586                 :          4 :          vertex_cache[vtx_id].y = cy + connect_len * midpoint_dir_y;
     587                 :            :          
     588         [ +  + ]:         28 :          for (ii = 0; ii < num_segments + extra_vtx; ii++) {
     589                 :         24 :             vertex_cache[ii].color = color;
     590                 :         24 :             vertex_cache[ii].z = 0;
     591                 :            :          }
     592                 :            :          
     593                 :          4 :          al_draw_prim(vertex_cache, 0, 0, 0, num_segments + extra_vtx, ALLEGRO_PRIM_TRIANGLE_FAN);
     594                 :            :          
     595                 :            :          /* Mirror the vertices and draw them again */
     596         [ +  + ]:         28 :          for (ii = 0; ii < num_segments + extra_vtx; ii++) {
     597                 :         24 :             float dot = (vertex_cache[ii].x - cx) * midpoint_dir_x + (vertex_cache[ii].y - cy) * midpoint_dir_y;
     598                 :         24 :             vertex_cache[ii].x = 2 * cx + 2 * dot * midpoint_dir_x - vertex_cache[ii].x;
     599                 :         24 :             vertex_cache[ii].y = 2 * cy + 2 * dot * midpoint_dir_y - vertex_cache[ii].y;
     600                 :            :          }
     601                 :            :          
     602                 :          4 :          al_draw_prim(vertex_cache, 0, 0, 0, num_segments + extra_vtx, ALLEGRO_PRIM_TRIANGLE_FAN);
     603                 :            :       } else {
     604                 :            :          /* Apex: 2 vertices if the apex is blunt) */
     605         [ #  # ]:          0 :          int extra_vtx = blunt_tip ? 2 : 1;
     606                 :            :          
     607                 :          0 :          num_segments = (2 * outer_side_angle) / (2 * ALLEGRO_PI) * ALLEGRO_PRIM_QUALITY * scale * sqrtf(r + ht);
     608                 :            :          
     609         [ #  # ]:          0 :          if (num_segments < 2)
     610                 :          0 :             num_segments = 2;
     611                 :            :          
     612         [ #  # ]:          0 :          if (num_segments + extra_vtx >= ALLEGRO_VERTEX_CACHE_SIZE)
     613                 :          0 :             num_segments = ALLEGRO_VERTEX_CACHE_SIZE - 1 - extra_vtx;
     614                 :            :            
     615                 :          0 :          al_calculate_arc(&(vertex_cache[1].x), sizeof(ALLEGRO_VERTEX), cx, cy, r + ht, r + ht, start_theta - outer_side_angle, 2 * outer_side_angle + delta_theta, 0, num_segments);
     616                 :            :          
     617         [ #  # ]:          0 :          if (blunt_tip) {
     618                 :          0 :             float vx = ht * (side_dir_y - side_dir_x);
     619                 :          0 :             float vy = ht * (-side_dir_x - side_dir_y);
     620                 :          0 :             float dot = vx * midpoint_dir_x + vy * midpoint_dir_y;
     621                 :            :             
     622                 :          0 :             vertex_cache[0].x = cx + vx;
     623                 :          0 :             vertex_cache[0].y = cy + vy;
     624                 :            :             
     625                 :          0 :             vx = 2 * dot * midpoint_dir_x - vx;
     626                 :          0 :             vy = 2 * dot * midpoint_dir_y - vy;
     627                 :            :             
     628                 :          0 :             vertex_cache[num_segments + 1].x = cx + vx;
     629                 :          0 :             vertex_cache[num_segments + 1].y = cy + vy;
     630                 :            :          } else {
     631                 :          0 :             vertex_cache[0].x = cx - connect_len * midpoint_dir_x;
     632                 :          0 :             vertex_cache[0].y = cy - connect_len * midpoint_dir_y;
     633                 :            :          }
     634                 :            :          
     635         [ #  # ]:          0 :          for (ii = 0; ii < num_segments + extra_vtx; ii++) {
     636                 :          0 :             vertex_cache[ii].color = color;
     637                 :          0 :             vertex_cache[ii].z = 0;
     638                 :            :          }
     639                 :            :          
     640                 :          0 :          al_draw_prim(vertex_cache, 0, 0, 0, num_segments + extra_vtx, ALLEGRO_PRIM_TRIANGLE_FAN);
     641                 :            :       }
     642                 :            :    }
     643                 :          4 : }
     644                 :            : 
     645                 :            : /* Function: al_draw_filled_pieslice
     646                 :            :  */
     647                 :          6 : void al_draw_filled_pieslice(float cx, float cy, float r, float start_theta,
     648                 :            :    float delta_theta, ALLEGRO_COLOR color)
     649                 :            : {
     650                 :            :    LOCAL_VERTEX_CACHE;
     651                 :          6 :    float scale = get_scale();
     652                 :            :    int num_segments, ii;
     653                 :            :    
     654 [ -  + ][ #  # ]:          6 :    ASSERT(r >= 0);
                 [ #  # ]
     655                 :            :    
     656                 :          6 :    num_segments = fabs(delta_theta / (2 * ALLEGRO_PI) * ALLEGRO_PRIM_QUALITY * scale * sqrtf(r));
     657                 :            : 
     658         [ -  + ]:          6 :    if (num_segments < 2)
     659                 :          0 :       num_segments = 2;
     660                 :            :    
     661         [ -  + ]:          6 :    if (num_segments + 1 >= ALLEGRO_VERTEX_CACHE_SIZE) {
     662                 :          0 :       num_segments = ALLEGRO_VERTEX_CACHE_SIZE - 1 - 1;
     663                 :            :    }
     664                 :            :       
     665                 :          6 :    al_calculate_arc(&(vertex_cache[1].x), sizeof(ALLEGRO_VERTEX), cx, cy, r, r, start_theta, delta_theta, 0, num_segments);
     666                 :          6 :    vertex_cache[0].x = cx; vertex_cache[0].y = cy;
     667                 :            :    
     668         [ +  + ]:        210 :    for (ii = 0; ii < num_segments + 1; ii++) {
     669                 :        204 :       vertex_cache[ii].color = color;
     670                 :        204 :       vertex_cache[ii].z = 0;
     671                 :            :    }
     672                 :            :    
     673                 :          6 :    al_draw_prim(vertex_cache, 0, 0, 0, num_segments + 1, ALLEGRO_PRIM_TRIANGLE_FAN);
     674                 :          6 : }
     675                 :            : 
     676                 :            : /* Function: al_draw_ellipse
     677                 :            :  */
     678                 :         22 : void al_draw_ellipse(float cx, float cy, float rx, float ry,
     679                 :            :    ALLEGRO_COLOR color, float thickness)
     680                 :            : {
     681                 :            :    LOCAL_VERTEX_CACHE;
     682                 :         22 :    float scale = get_scale();
     683                 :            : 
     684 [ -  + ][ #  # ]:         22 :    ASSERT(rx >= 0);
                 [ #  # ]
     685 [ -  + ][ #  # ]:         22 :    ASSERT(ry >= 0);
                 [ #  # ]
     686                 :            : 
     687         [ +  + ]:         22 :    if (thickness > 0) {
     688                 :         20 :       int num_segments = ALLEGRO_PRIM_QUALITY * scale * sqrtf((rx + ry) / 2.0f);
     689                 :            :       int ii;
     690                 :            : 
     691                 :            :       /* In case rx and ry are both 0. */
     692         [ +  + ]:         20 :       if (num_segments < 2)
     693                 :            :          return;
     694                 :            : 
     695         [ +  + ]:         18 :       if (2 * num_segments >= ALLEGRO_VERTEX_CACHE_SIZE) {
     696                 :          2 :          num_segments = (ALLEGRO_VERTEX_CACHE_SIZE - 1) / 2;
     697                 :            :       }
     698                 :            :       
     699                 :         18 :       al_calculate_arc(&(vertex_cache[0].x), sizeof(ALLEGRO_VERTEX), cx, cy, rx, ry, 0, ALLEGRO_PI * 2, thickness, num_segments);
     700         [ +  + ]:       4062 :       for (ii = 0; ii < 2 * num_segments; ii++) {
     701                 :       4044 :          vertex_cache[ii].color = color;
     702                 :       4044 :          vertex_cache[ii].z = 0;
     703                 :            :       }
     704                 :            :          
     705                 :         18 :       al_draw_prim(vertex_cache, 0, 0, 0, 2 * num_segments, ALLEGRO_PRIM_TRIANGLE_STRIP);
     706                 :            :    } else {
     707                 :          2 :       int num_segments = ALLEGRO_PRIM_QUALITY * scale * sqrtf((rx + ry) / 2.0f);
     708                 :            :       int ii;
     709                 :            :       
     710                 :            :       /* In case rx and ry are both 0. */
     711         [ +  - ]:          2 :       if (num_segments < 2)
     712                 :            :          return;
     713                 :            : 
     714         [ -  + ]:          2 :       if (num_segments >= ALLEGRO_VERTEX_CACHE_SIZE) {
     715                 :          0 :          num_segments = ALLEGRO_VERTEX_CACHE_SIZE - 1;
     716                 :            :       }
     717                 :            : 
     718                 :          2 :       al_calculate_arc(&(vertex_cache[0].x), sizeof(ALLEGRO_VERTEX), cx, cy, rx, ry, 0, ALLEGRO_PI * 2, 0, num_segments);
     719         [ +  + ]:        226 :       for (ii = 0; ii < num_segments; ii++) {
     720                 :        224 :          vertex_cache[ii].color = color;
     721                 :        224 :          vertex_cache[ii].z = 0;
     722                 :            :       }
     723                 :            :          
     724                 :         22 :       al_draw_prim(vertex_cache, 0, 0, 0, num_segments - 1, ALLEGRO_PRIM_LINE_LOOP);
     725                 :            :    }
     726                 :            : }
     727                 :            : 
     728                 :            : /* Function: al_draw_filled_ellipse
     729                 :            :  */
     730                 :         12 : void al_draw_filled_ellipse(float cx, float cy, float rx, float ry,
     731                 :            :    ALLEGRO_COLOR color)
     732                 :            : {
     733                 :            :    LOCAL_VERTEX_CACHE;
     734                 :            :    int num_segments, ii;
     735                 :         12 :    float scale = get_scale();
     736                 :            : 
     737 [ -  + ][ #  # ]:         12 :    ASSERT(rx >= 0);
                 [ #  # ]
     738 [ -  + ][ #  # ]:         12 :    ASSERT(ry >= 0);
                 [ #  # ]
     739                 :            :    
     740                 :         12 :    num_segments = ALLEGRO_PRIM_QUALITY * scale * sqrtf((rx + ry) / 2.0f);
     741                 :            : 
     742                 :            :    /* In case rx and ry are both close to 0. If al_calculate_arc is passed
     743                 :            :     * 0 or 1 it will assert.
     744                 :            :     */
     745         [ +  - ]:         12 :    if (num_segments < 2)
     746                 :         12 :       return;
     747                 :            :    
     748         [ -  + ]:         12 :    if (num_segments >= ALLEGRO_VERTEX_CACHE_SIZE) {
     749                 :          0 :       num_segments = ALLEGRO_VERTEX_CACHE_SIZE - 1;
     750                 :            :    }
     751                 :            :       
     752                 :         12 :    al_calculate_arc(&(vertex_cache[1].x), sizeof(ALLEGRO_VERTEX), cx, cy, rx, ry, 0, ALLEGRO_PI * 2, 0, num_segments);
     753                 :         12 :    vertex_cache[0].x = cx; vertex_cache[0].y = cy;
     754                 :            :    
     755         [ +  + ]:       1026 :    for (ii = 0; ii < num_segments + 1; ii++) {
     756                 :       1014 :       vertex_cache[ii].color = color;
     757                 :       1014 :       vertex_cache[ii].z = 0;
     758                 :            :    }
     759                 :            :    
     760                 :         12 :    al_draw_prim(vertex_cache, 0, 0, 0, num_segments + 1, ALLEGRO_PRIM_TRIANGLE_FAN);
     761                 :            : }
     762                 :            : 
     763                 :            : /* Function: al_draw_circle
     764                 :            :  */
     765                 :          4 : void al_draw_circle(float cx, float cy, float r, ALLEGRO_COLOR color,
     766                 :            :    float thickness)
     767                 :            : {
     768                 :          4 :    al_draw_ellipse(cx, cy, r, r, color, thickness);
     769                 :          4 : }
     770                 :            : 
     771                 :            : /* Function: al_draw_filled_circle
     772                 :            :  */
     773                 :          2 : void al_draw_filled_circle(float cx, float cy, float r, ALLEGRO_COLOR color)
     774                 :            : {
     775                 :          2 :    al_draw_filled_ellipse(cx, cy, r, r, color);
     776                 :          2 : }
     777                 :            : 
     778                 :            : /* Function: al_draw_elliptical_arc
     779                 :            :  */
     780                 :         34 : void al_draw_elliptical_arc(float cx, float cy, float rx, float ry, float start_theta,
     781                 :            :    float delta_theta, ALLEGRO_COLOR color, float thickness)
     782                 :            : {
     783                 :            :    LOCAL_VERTEX_CACHE;
     784                 :         34 :    float scale = get_scale();
     785                 :            : 
     786 [ +  - ][ -  + ]:         34 :    ASSERT(rx >= 0 && ry >= 0);
         [ #  # ][ #  # ]
                 [ #  # ]
     787         [ +  + ]:         34 :    if (thickness > 0) {
     788                 :         30 :       int num_segments = fabs(delta_theta / (2 * ALLEGRO_PI) * ALLEGRO_PRIM_QUALITY * scale * sqrtf((rx + ry) / 2.0f));
     789                 :            :       int ii;
     790                 :            : 
     791         [ +  + ]:         30 :       if (num_segments < 2)
     792                 :          2 :          num_segments = 2;
     793                 :            : 
     794         [ -  + ]:         30 :       if (2 * num_segments >= ALLEGRO_VERTEX_CACHE_SIZE) {
     795                 :          0 :          num_segments = (ALLEGRO_VERTEX_CACHE_SIZE - 1) / 2;
     796                 :            :       }
     797                 :            : 
     798                 :         30 :       al_calculate_arc(&(vertex_cache[0].x), sizeof(ALLEGRO_VERTEX), cx, cy, rx, ry, start_theta, delta_theta, thickness, num_segments);
     799                 :            :       
     800         [ +  + ]:       3514 :       for (ii = 0; ii < 2 * num_segments; ii++) {
     801                 :       3484 :          vertex_cache[ii].color = color;
     802                 :       3484 :          vertex_cache[ii].z = 0;
     803                 :            :       }
     804                 :            :       
     805                 :         30 :       al_draw_prim(vertex_cache, 0, 0, 0, 2 * num_segments, ALLEGRO_PRIM_TRIANGLE_STRIP);
     806                 :            :    } else {
     807                 :          4 :       int num_segments = fabs(delta_theta / (2 * ALLEGRO_PI) * ALLEGRO_PRIM_QUALITY * scale * sqrtf((rx + ry) / 2.0f));
     808                 :            :       int ii;
     809                 :            : 
     810         [ -  + ]:          4 :       if (num_segments < 2)
     811                 :          0 :          num_segments = 2;
     812                 :            : 
     813         [ -  + ]:          4 :       if (num_segments >= ALLEGRO_VERTEX_CACHE_SIZE) {
     814                 :          0 :          num_segments = ALLEGRO_VERTEX_CACHE_SIZE - 1;
     815                 :            :       }
     816                 :            :       
     817                 :          4 :       al_calculate_arc(&(vertex_cache[0].x), sizeof(ALLEGRO_VERTEX), cx, cy, rx, ry, start_theta, delta_theta, 0, num_segments);
     818                 :            :       
     819         [ +  + ]:        234 :       for (ii = 0; ii < num_segments; ii++) {
     820                 :        230 :          vertex_cache[ii].color = color;
     821                 :        230 :          vertex_cache[ii].z = 0;
     822                 :            :       }
     823                 :            :       
     824                 :          4 :       al_draw_prim(vertex_cache, 0, 0, 0, num_segments, ALLEGRO_PRIM_LINE_STRIP);
     825                 :            :    }
     826                 :         34 : }
     827                 :            : 
     828                 :            : /* Function: al_draw_arc
     829                 :            :  */
     830                 :         22 : void al_draw_arc(float cx, float cy, float r, float start_theta,
     831                 :            :    float delta_theta, ALLEGRO_COLOR color, float thickness)
     832                 :            : {
     833                 :         22 :    al_draw_elliptical_arc(cx, cy, r, r, start_theta, delta_theta, color, thickness);
     834                 :         22 : }
     835                 :            : 
     836                 :            : /* Function: al_draw_rounded_rectangle
     837                 :            :  */
     838                 :         18 : void al_draw_rounded_rectangle(float x1, float y1, float x2, float y2,
     839                 :            :    float rx, float ry, ALLEGRO_COLOR color, float thickness)
     840                 :            : {
     841                 :            :    LOCAL_VERTEX_CACHE;
     842                 :         18 :    float scale = get_scale();
     843                 :            : 
     844 [ -  + ][ #  # ]:         18 :    ASSERT(rx >= 0);
                 [ #  # ]
     845 [ -  + ][ #  # ]:         18 :    ASSERT(ry >= 0);
                 [ #  # ]
     846                 :            : 
     847         [ +  + ]:         18 :    if (thickness > 0) {
     848                 :         16 :       int num_segments = ALLEGRO_PRIM_QUALITY * scale * sqrtf((rx + ry) / 2.0f) / 4;
     849                 :            :       int ii;
     850                 :            : 
     851                 :            :       /* In case rx and ry are both 0. */
     852         [ +  + ]:         16 :       if (num_segments < 2) {
     853                 :          2 :          al_draw_rectangle(x1, y1, x2, y2, color, thickness);
     854                 :            :          return;
     855                 :            :       }
     856                 :            : 
     857         [ -  + ]:         14 :       if (8 * num_segments + 2 >= ALLEGRO_VERTEX_CACHE_SIZE) {
     858                 :          0 :          num_segments = (ALLEGRO_VERTEX_CACHE_SIZE - 3) / 8;
     859                 :            :       }
     860                 :            :       
     861                 :         14 :       al_calculate_arc(&(vertex_cache[0].x), sizeof(ALLEGRO_VERTEX), 0, 0, rx, ry, 0, ALLEGRO_PI / 2, thickness, num_segments);
     862                 :            :       
     863         [ +  + ]:        238 :       for (ii = 0; ii < 2 * num_segments; ii += 2) {
     864                 :        224 :          vertex_cache[ii + 2 * num_segments + 1].x = x1 + rx - vertex_cache[2 * num_segments - 1 - ii].x;
     865                 :        224 :          vertex_cache[ii + 2 * num_segments + 1].y = y1 + ry - vertex_cache[2 * num_segments - 1 - ii].y;
     866                 :        224 :          vertex_cache[ii + 2 * num_segments].x = x1 + rx - vertex_cache[2 * num_segments - 1 - ii - 1].x;
     867                 :        224 :          vertex_cache[ii + 2 * num_segments].y = y1 + ry - vertex_cache[2 * num_segments - 1 - ii - 1].y;
     868                 :            : 
     869                 :        224 :          vertex_cache[ii + 4 * num_segments].x = x1 + rx - vertex_cache[ii].x;
     870                 :        224 :          vertex_cache[ii + 4 * num_segments].y = y2 - ry + vertex_cache[ii].y;
     871                 :        224 :          vertex_cache[ii + 4 * num_segments + 1].x = x1 + rx - vertex_cache[ii + 1].x;
     872                 :        224 :          vertex_cache[ii + 4 * num_segments + 1].y = y2 - ry + vertex_cache[ii + 1].y;
     873                 :            : 
     874                 :        224 :          vertex_cache[ii + 6 * num_segments + 1].x = x2 - rx + vertex_cache[2 * num_segments - 1 - ii].x;
     875                 :        224 :          vertex_cache[ii + 6 * num_segments + 1].y = y2 - ry + vertex_cache[2 * num_segments - 1 - ii].y;
     876                 :        224 :          vertex_cache[ii + 6 * num_segments].x = x2 - rx + vertex_cache[2 * num_segments - 1 - ii - 1].x;
     877                 :        224 :          vertex_cache[ii + 6 * num_segments].y = y2 - ry + vertex_cache[2 * num_segments - 1 - ii - 1].y;
     878                 :            :       }
     879         [ +  + ]:        238 :       for (ii = 0; ii < 2 * num_segments; ii += 2) {
     880                 :        224 :          vertex_cache[ii].x = x2 - rx + vertex_cache[ii].x;
     881                 :        224 :          vertex_cache[ii].y = y1 + ry - vertex_cache[ii].y;
     882                 :        224 :          vertex_cache[ii + 1].x = x2 - rx + vertex_cache[ii + 1].x;
     883                 :        224 :          vertex_cache[ii + 1].y = y1 + ry - vertex_cache[ii + 1].y;
     884                 :            :       }
     885                 :         14 :       vertex_cache[8 * num_segments] = vertex_cache[0];
     886                 :         14 :       vertex_cache[8 * num_segments + 1] = vertex_cache[1];
     887                 :            : 
     888         [ +  + ]:       1834 :       for (ii = 0; ii < 8 * num_segments + 2; ii++) {
     889                 :       1820 :          vertex_cache[ii].color = color;
     890                 :       1820 :          vertex_cache[ii].z = 0;
     891                 :            :       }
     892                 :            :          
     893                 :         14 :       al_draw_prim(vertex_cache, 0, 0, 0, 8 * num_segments + 2, ALLEGRO_PRIM_TRIANGLE_STRIP);
     894                 :            :    } else {
     895                 :          2 :       int num_segments = ALLEGRO_PRIM_QUALITY * scale * sqrtf((rx + ry) / 2.0f) / 4;
     896                 :            :       int ii;
     897                 :            :       
     898                 :            :       /* In case rx and ry are both 0. */
     899         [ -  + ]:          2 :       if (num_segments < 2) {
     900                 :          0 :          al_draw_rectangle(x1, y1, x2, y2, color, thickness);
     901                 :            :          return;
     902                 :            :       }
     903                 :            : 
     904         [ -  + ]:          2 :       if (num_segments * 4 >= ALLEGRO_VERTEX_CACHE_SIZE) {
     905                 :          0 :          num_segments = (ALLEGRO_VERTEX_CACHE_SIZE - 1) / 4;
     906                 :            :       }
     907                 :            :       
     908                 :          2 :       al_calculate_arc(&(vertex_cache[0].x), sizeof(ALLEGRO_VERTEX), 0, 0, rx, ry, 0, ALLEGRO_PI / 2, 0, num_segments + 1);
     909                 :            : 
     910         [ +  + ]:         34 :       for (ii = 0; ii < num_segments; ii++) {
     911                 :         32 :          vertex_cache[ii + 1 * num_segments].x = x1 + rx - vertex_cache[num_segments - 1 - ii].x;
     912                 :         32 :          vertex_cache[ii + 1 * num_segments].y = y1 + ry - vertex_cache[num_segments - 1 - ii].y;
     913                 :            : 
     914                 :         32 :          vertex_cache[ii + 2 * num_segments].x = x1 + rx - vertex_cache[ii].x;
     915                 :         32 :          vertex_cache[ii + 2 * num_segments].y = y2 - ry + vertex_cache[ii].y;
     916                 :            : 
     917                 :         32 :          vertex_cache[ii + 3 * num_segments].x = x2 - rx + vertex_cache[num_segments - 1 - ii].x;
     918                 :         32 :          vertex_cache[ii + 3 * num_segments].y = y2 - ry + vertex_cache[num_segments - 1 - ii].y;
     919                 :            :       }
     920         [ +  + ]:         34 :       for (ii = 0; ii < num_segments; ii++) {
     921                 :         32 :          vertex_cache[ii].x = x2 - rx + vertex_cache[ii].x;
     922                 :         32 :          vertex_cache[ii].y = y1 + ry - vertex_cache[ii].y;
     923                 :            :       }
     924                 :            : 
     925         [ +  + ]:        130 :       for (ii = 0; ii < 4 * num_segments; ii++) {
     926                 :        128 :          vertex_cache[ii].color = color;
     927                 :        128 :          vertex_cache[ii].z = 0;
     928                 :            :       }
     929                 :            :          
     930                 :         18 :       al_draw_prim(vertex_cache, 0, 0, 0, 4 * num_segments, ALLEGRO_PRIM_LINE_LOOP);
     931                 :            :    }
     932                 :            : }
     933                 :            : 
     934                 :            : /* Function: al_draw_filled_rounded_rectangle
     935                 :            :  */
     936                 :         12 : void al_draw_filled_rounded_rectangle(float x1, float y1, float x2, float y2,
     937                 :            :    float rx, float ry, ALLEGRO_COLOR color)
     938                 :            : {
     939                 :            :    LOCAL_VERTEX_CACHE;
     940                 :            :    int ii;
     941                 :         12 :    float scale = get_scale();
     942                 :         12 :    int num_segments = ALLEGRO_PRIM_QUALITY * scale * sqrtf((rx + ry) / 2.0f) / 4;
     943                 :            : 
     944 [ -  + ][ #  # ]:         12 :    ASSERT(rx >= 0);
                 [ #  # ]
     945 [ -  + ][ #  # ]:         12 :    ASSERT(ry >= 0);
                 [ #  # ]
     946                 :            :    
     947                 :            :    /* In case rx and ry are both 0. */
     948         [ +  + ]:         12 :    if (num_segments < 2) {
     949                 :          2 :       al_draw_filled_rectangle(x1, y1, x2, y2, color);
     950                 :         12 :       return;
     951                 :            :    }
     952                 :            : 
     953         [ -  + ]:         10 :    if (num_segments * 4 >= ALLEGRO_VERTEX_CACHE_SIZE) {
     954                 :          0 :       num_segments = (ALLEGRO_VERTEX_CACHE_SIZE - 1) / 4;
     955                 :            :    }
     956                 :            :    
     957                 :         10 :    al_calculate_arc(&(vertex_cache[0].x), sizeof(ALLEGRO_VERTEX), 0, 0, rx, ry, 0, ALLEGRO_PI / 2, 0, num_segments + 1);
     958                 :            : 
     959         [ +  + ]:        150 :    for (ii = 0; ii < num_segments; ii++) {
     960                 :        140 :       vertex_cache[ii + 1 * num_segments].x = x1 + rx - vertex_cache[num_segments - 1 - ii].x;
     961                 :        140 :       vertex_cache[ii + 1 * num_segments].y = y1 + ry - vertex_cache[num_segments - 1 - ii].y;
     962                 :            : 
     963                 :        140 :       vertex_cache[ii + 2 * num_segments].x = x1 + rx - vertex_cache[ii].x;
     964                 :        140 :       vertex_cache[ii + 2 * num_segments].y = y2 - ry + vertex_cache[ii].y;
     965                 :            : 
     966                 :        140 :       vertex_cache[ii + 3 * num_segments].x = x2 - rx + vertex_cache[num_segments - 1 - ii].x;
     967                 :        140 :       vertex_cache[ii + 3 * num_segments].y = y2 - ry + vertex_cache[num_segments - 1 - ii].y;
     968                 :            :    }
     969         [ +  + ]:        150 :    for (ii = 0; ii < num_segments; ii++) {
     970                 :        140 :       vertex_cache[ii].x = x2 - rx + vertex_cache[ii].x;
     971                 :        140 :       vertex_cache[ii].y = y1 + ry - vertex_cache[ii].y;
     972                 :            :    }
     973                 :            : 
     974         [ +  + ]:        570 :    for (ii = 0; ii < 4 * num_segments; ii++) {
     975                 :        560 :       vertex_cache[ii].color = color;
     976                 :        560 :       vertex_cache[ii].z = 0;
     977                 :            :    }
     978                 :            : 
     979                 :            :    /*
     980                 :            :    TODO: Doing this as a triangle fan just doesn't sound all that great, perhaps shuffle the vertices somehow to at least make it a strip
     981                 :            :    */
     982                 :         10 :    al_draw_prim(vertex_cache, 0, 0, 0, 4 * num_segments, ALLEGRO_PRIM_TRIANGLE_FAN);
     983                 :            : }
     984                 :            : 
     985                 :            : /* Function: al_calculate_spline
     986                 :            :  */
     987                 :         16 : void al_calculate_spline(float* dest, int stride, float points[8],
     988                 :            :    float thickness, int num_segments)
     989                 :            : {
     990                 :            :    /* Derivatives of x(t) and y(t). */
     991                 :            :    float x, dx, ddx, dddx;
     992                 :            :    float y, dy, ddy, dddy;
     993                 :         16 :    int ii = 0;
     994                 :            :    
     995                 :            :    /* Temp variables used in the setup. */
     996                 :            :    float dt, dt2, dt3;
     997                 :            :    float xdt2_term, xdt3_term;
     998                 :            :    float ydt2_term, ydt3_term;
     999                 :            : 
    1000                 :            :    /* This is enough to avoid malloc in ex_prim, which I take as a reasonable
    1001                 :            :     * guess to what a common number of segments might be.  To be honest, it
    1002                 :            :     * probably makes no difference.
    1003                 :            :     */
    1004                 :            :    float cache_point_buffer_storage[150];
    1005                 :         16 :    float* cache_point_buffer = cache_point_buffer_storage;
    1006                 :            : 
    1007 [ -  + ][ #  # ]:         16 :    ASSERT(num_segments > 1);
                 [ #  # ]
    1008 [ -  + ][ #  # ]:         16 :    ASSERT(points);
                 [ #  # ]
    1009                 :            : 
    1010         [ -  + ]:         16 :    if (num_segments > (int)(sizeof(cache_point_buffer_storage) / sizeof(float) / 2)) {
    1011                 :          0 :       cache_point_buffer = al_malloc(2 * sizeof(float) * num_segments);
    1012                 :            :    }
    1013                 :            : 
    1014                 :         16 :    dt = 1.0 / (num_segments - 1);
    1015                 :         16 :    dt2 = (dt * dt);
    1016                 :         16 :    dt3 = (dt2 * dt);
    1017                 :            :    
    1018                 :            :    /* x coordinates. */
    1019                 :         16 :    xdt2_term = 3 * (points[4] - 2 * points[2] + points[0]);
    1020                 :         16 :    xdt3_term = points[6] + 3 * (-points[4] + points[2]) - points[0];
    1021                 :            :    
    1022                 :         16 :    xdt2_term = dt2 * xdt2_term;
    1023                 :         16 :    xdt3_term = dt3 * xdt3_term;
    1024                 :            :    
    1025                 :         16 :    dddx = 6 * xdt3_term;
    1026                 :         16 :    ddx = -6 * xdt3_term + 2 * xdt2_term;
    1027                 :         16 :    dx = xdt3_term - xdt2_term + 3 * dt * (points[2] - points[0]);
    1028                 :         16 :    x = points[0];
    1029                 :            :    
    1030                 :            :    /* y coordinates. */
    1031                 :         16 :    ydt2_term = 3 * (points[5] - 2 * points[3] + points[1]);
    1032                 :         16 :    ydt3_term = points[7] + 3 * (-points[5] + points[3]) - points[1];
    1033                 :            :    
    1034                 :         16 :    ydt2_term = dt2 * ydt2_term;
    1035                 :         16 :    ydt3_term = dt3 * ydt3_term;
    1036                 :            :    
    1037                 :         16 :    dddy = 6 * ydt3_term;
    1038                 :         16 :    ddy = -6 * ydt3_term + 2 * ydt2_term;
    1039                 :         16 :    dy = ydt3_term - ydt2_term + dt * 3 * (points[3] - points[1]);
    1040                 :         16 :    y = points[1];
    1041                 :            :    
    1042                 :         16 :    cache_point_buffer[2 * ii] = x;
    1043                 :         16 :    cache_point_buffer[2 * ii + 1] = y;
    1044                 :            :    
    1045         [ +  + ]:        848 :    for (ii = 1; ii < num_segments; ii++) {
    1046                 :        832 :       ddx += dddx;
    1047                 :        832 :       dx += ddx;
    1048                 :        832 :       x += dx;
    1049                 :            :       
    1050                 :        832 :       ddy += dddy;
    1051                 :        832 :       dy += ddy;
    1052                 :        832 :       y += dy;
    1053                 :            :       
    1054                 :        832 :       cache_point_buffer[2 * ii] = x;
    1055                 :        832 :       cache_point_buffer[2 * ii + 1] = y;
    1056                 :            :    }
    1057                 :         16 :    al_calculate_ribbon(dest, stride, cache_point_buffer, 2 * sizeof(float), thickness, num_segments);
    1058                 :            : 
    1059         [ -  + ]:         16 :    if (cache_point_buffer != cache_point_buffer_storage) {
    1060                 :          0 :       al_free(cache_point_buffer);
    1061                 :            :    }
    1062                 :         16 : }
    1063                 :            : 
    1064                 :            : /* Function: al_draw_spline
    1065                 :            :  */
    1066                 :         16 : void al_draw_spline(float points[8], ALLEGRO_COLOR color, float thickness)
    1067                 :            : {
    1068                 :            :    int ii;
    1069                 :         16 :    float scale = get_scale();
    1070                 :         64 :    int num_segments = (int)(sqrtf(hypotf(points[2] - points[0], points[3] - points[1]) +
    1071                 :         16 :                                   hypotf(points[4] - points[2], points[5] - points[3]) +
    1072                 :         32 :                                   hypotf(points[6] - points[4], points[7] - points[5])) *
    1073                 :         16 :                             1.2 * ALLEGRO_PRIM_QUALITY * scale / 10);
    1074                 :            :    LOCAL_VERTEX_CACHE;
    1075                 :            :    
    1076         [ -  + ]:         16 :    if(num_segments < 2)
    1077                 :          0 :       num_segments = 2;
    1078                 :            : 
    1079         [ +  + ]:         16 :    if (thickness > 0) {
    1080         [ -  + ]:         14 :       if (2 * num_segments >= ALLEGRO_VERTEX_CACHE_SIZE) {
    1081                 :          0 :          num_segments = (ALLEGRO_VERTEX_CACHE_SIZE - 1) / 2;
    1082                 :            :       }
    1083                 :            :          
    1084                 :         14 :       al_calculate_spline(&(vertex_cache[0].x), sizeof(ALLEGRO_VERTEX), points, thickness, num_segments);
    1085                 :            :       
    1086         [ +  + ]:       1498 :       for (ii = 0; ii < 2 * num_segments; ii++) {
    1087                 :       1484 :          vertex_cache[ii].color = color;
    1088                 :       1484 :          vertex_cache[ii].z = 0;
    1089                 :            :       }
    1090                 :            :       
    1091                 :         14 :       al_draw_prim(vertex_cache, 0, 0, 0, 2 * num_segments, ALLEGRO_PRIM_TRIANGLE_STRIP);
    1092                 :            :    } else {
    1093         [ -  + ]:          2 :       if (num_segments >= ALLEGRO_VERTEX_CACHE_SIZE) {
    1094                 :          0 :          num_segments = ALLEGRO_VERTEX_CACHE_SIZE - 1;
    1095                 :            :       }
    1096                 :            :          
    1097                 :          2 :       al_calculate_spline(&(vertex_cache[0].x), sizeof(ALLEGRO_VERTEX), points, thickness, num_segments);
    1098                 :            :       
    1099         [ +  + ]:        108 :       for (ii = 0; ii < num_segments; ii++) {
    1100                 :        106 :          vertex_cache[ii].color = color;
    1101                 :        106 :          vertex_cache[ii].z = 0;
    1102                 :            :       }
    1103                 :            :       
    1104                 :          2 :       al_draw_prim(vertex_cache, 0, 0, 0, num_segments, ALLEGRO_PRIM_LINE_STRIP);
    1105                 :            :    }
    1106                 :         16 : }
    1107                 :            : 
    1108                 :            : /* Function: al_calculate_ribbon
    1109                 :            :  */
    1110                 :         16 : void al_calculate_ribbon(float* dest, int dest_stride, const float *points,
    1111                 :            :    int points_stride, float thickness, int num_segments)
    1112                 :            : {
    1113 [ -  + ][ #  # ]:         16 :    ASSERT(points);
                 [ #  # ]
    1114 [ -  + ][ #  # ]:         16 :    ASSERT(num_segments >= 2);
                 [ #  # ]
    1115                 :            : 
    1116         [ +  + ]:         16 :    if (thickness > 0) {
    1117                 :         14 :       int ii = 0;
    1118                 :            :       float x, y;
    1119                 :            :       
    1120                 :            :       float cur_dir_x;
    1121                 :            :       float cur_dir_y;
    1122                 :         14 :       float prev_dir_x = 0;
    1123                 :         14 :       float prev_dir_y = 0;
    1124                 :         14 :       float t = thickness / 2;
    1125                 :            :       float tx, ty;
    1126                 :            :       float nx, ny;
    1127                 :         14 :       float sign = 1;
    1128                 :            :       
    1129         [ +  + ]:        742 :       for (ii = 0; ii < 2 * num_segments - 2; ii += 2) {
    1130                 :            :          float dir_len;
    1131                 :        728 :          x = *points;
    1132                 :        728 :          y = *(points + 1);
    1133                 :            : 
    1134                 :        728 :          points = (float*)(((char*)points) + points_stride);
    1135                 :            :          
    1136                 :        728 :          cur_dir_x = *(points)     - x;
    1137                 :        728 :          cur_dir_y = *(points + 1) - y;
    1138                 :            :          
    1139                 :        728 :          dir_len = hypotf(cur_dir_x, cur_dir_y);
    1140                 :            :          
    1141         [ +  - ]:        728 :          if(dir_len > 0.000001f) {
    1142                 :        728 :             cur_dir_x /= dir_len;
    1143                 :        728 :             cur_dir_y /= dir_len;
    1144         [ #  # ]:          0 :          } else if (ii == 0) {
    1145                 :            :             cur_dir_x = 1;
    1146                 :            :             cur_dir_y = 0;
    1147                 :            :          } else {
    1148                 :          0 :             cur_dir_x = prev_dir_x;
    1149                 :          0 :             cur_dir_y = prev_dir_y;
    1150                 :            :          }
    1151                 :            :          
    1152         [ +  + ]:        728 :          if (ii == 0) {
    1153                 :         14 :             tx = -t * cur_dir_y;
    1154                 :         14 :             ty = t * cur_dir_x;
    1155                 :         14 :             nx = 0;
    1156                 :         14 :             ny = 0;
    1157                 :            :          } else {
    1158                 :        714 :             float dot = cur_dir_x * prev_dir_x + cur_dir_y * prev_dir_y;
    1159                 :            :             float norm_len, cosine;
    1160         [ -  + ]:        714 :             if(dot < 0) {
    1161                 :            :                /*
    1162                 :            :                 * This is by no means exact, but seems to produce acceptable results
    1163                 :            :                 */
    1164                 :            :                float tx_;
    1165                 :          0 :                tx = cur_dir_x - prev_dir_x;
    1166                 :          0 :                ty = cur_dir_y - prev_dir_y;
    1167                 :          0 :                norm_len = hypotf(tx, ty);
    1168                 :            :                
    1169                 :          0 :                tx /= norm_len;
    1170                 :          0 :                ty /= norm_len;
    1171                 :            :                
    1172                 :          0 :                cosine = tx * cur_dir_x + ty * cur_dir_y;
    1173                 :            :                
    1174                 :          0 :                nx = -t * tx / cosine;
    1175                 :          0 :                ny = -t * ty / cosine;
    1176                 :          0 :                tx_ = tx;
    1177                 :          0 :                tx =  -t * ty * cosine;
    1178                 :          0 :                ty =  t * tx_ * cosine;
    1179                 :          0 :                sign = -sign;
    1180                 :            :             } else {
    1181                 :            :                float new_norm_len;
    1182                 :        714 :                tx = cur_dir_y + prev_dir_y;
    1183                 :        714 :                ty = -(cur_dir_x + prev_dir_x);
    1184                 :        714 :                norm_len = hypotf(tx, ty);
    1185                 :            :   
    1186                 :        714 :                tx /= norm_len;
    1187                 :        714 :                ty /= norm_len;
    1188                 :        714 :                cosine = tx * (-cur_dir_y) + ty * (cur_dir_x);
    1189                 :        714 :                new_norm_len = t / cosine;
    1190                 :            :                
    1191                 :        714 :                tx *= new_norm_len;
    1192                 :        714 :                ty *= new_norm_len;
    1193                 :        714 :                nx = 0;
    1194                 :        714 :                ny = 0;
    1195                 :            :             }
    1196                 :            :          }
    1197                 :            :          
    1198                 :        728 :          *dest =       x - sign * tx + nx;
    1199                 :        728 :          *(dest + 1) = y - sign * ty + ny;
    1200                 :        728 :          dest = (float*)(((char*)dest) + dest_stride);
    1201                 :        728 :          *dest =       x + sign * tx + nx;
    1202                 :        728 :          *(dest + 1) = y + sign * ty + ny;
    1203                 :        728 :          dest = (float*)(((char*)dest) + dest_stride);
    1204                 :            :          
    1205                 :        728 :          prev_dir_x = cur_dir_x;
    1206                 :        728 :          prev_dir_y = cur_dir_y;
    1207                 :            :       }
    1208                 :         14 :       tx = -t * prev_dir_y;
    1209                 :         14 :       ty = t * prev_dir_x;
    1210                 :            :       
    1211                 :         14 :       x = *points;
    1212                 :         14 :       y = *(points + 1);
    1213                 :            :       
    1214                 :         14 :       *dest =       x - sign * tx;
    1215                 :         14 :       *(dest + 1) = y - sign * ty;
    1216                 :         14 :       dest = (float*)(((char*)dest) + dest_stride);
    1217                 :         14 :       *dest =       x + sign * tx;
    1218                 :         14 :       *(dest + 1) = y + sign * ty;
    1219                 :            :    } else {
    1220                 :            :       int ii;
    1221         [ +  + ]:        108 :       for (ii = 0; ii < num_segments; ii++) {
    1222                 :        106 :          *dest =       *points;
    1223                 :        106 :          *(dest + 1) = *(points + 1);
    1224                 :        106 :          dest = (float*)(((char*)dest) + dest_stride);
    1225                 :        106 :          points = (float*)(((char*)points) + points_stride);
    1226                 :            :       }
    1227                 :            :    }
    1228                 :         16 : }
    1229                 :            : 
    1230                 :            : /* Function: al_draw_ribbon
    1231                 :            :  */
    1232                 :          0 : void al_draw_ribbon(const float *points, int points_stride, ALLEGRO_COLOR color,
    1233                 :            :    float thickness, int num_segments)
    1234                 :            : {
    1235                 :            :    LOCAL_VERTEX_CACHE;
    1236                 :            :    int ii;
    1237                 :            : 
    1238                 :          0 :    al_calculate_ribbon(&(vertex_cache[0].x), sizeof(ALLEGRO_VERTEX), points, points_stride, thickness, num_segments);
    1239                 :            :    
    1240         [ #  # ]:          0 :    if (thickness > 0) {
    1241         [ #  # ]:          0 :       for (ii = 0; ii < 2 * num_segments; ii++) {
    1242                 :          0 :          vertex_cache[ii].color = color;
    1243                 :          0 :          vertex_cache[ii].z = 0;
    1244                 :            :       }
    1245                 :            :       
    1246                 :          0 :       al_draw_prim(vertex_cache, 0, 0, 0, 2 * num_segments, ALLEGRO_PRIM_TRIANGLE_STRIP);
    1247                 :            :    } else {
    1248         [ #  # ]:          0 :       for (ii = 0; ii < num_segments; ii++) {
    1249                 :          0 :          vertex_cache[ii].color = color;
    1250                 :          0 :          vertex_cache[ii].z = 0;
    1251                 :            :       }
    1252                 :            :       
    1253                 :          0 :       al_draw_prim(vertex_cache, 0, 0, 0, num_segments, ALLEGRO_PRIM_LINE_STRIP);
    1254                 :            :    }
    1255                 :          0 : }
    1256                 :            : 
    1257                 :            : /* vim: set sts=3 sw=3 et: */

Generated by: LCOV version 1.9