1//----------------------------------------------------------------------------
2// Anti-Grain Geometry - Version 2.4
3// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4//
5// Permission to copy, use, modify, sell and distribute this software
6// is granted provided this copyright notice appears in all copies.
7// This software is provided "as is" without express or implied
8// warranty, and with no claim as to its suitability for any purpose.
9//
10//----------------------------------------------------------------------------
11// Contact: mcseem@antigrain.com
12//          mcseemagg@yahoo.com
13//          http://www.antigrain.com
14//----------------------------------------------------------------------------
15#ifndef AGG_LINE_AA_BASICS_INCLUDED
16#define AGG_LINE_AA_BASICS_INCLUDED
17
18#include <stdlib.h>
19#include "agg_basics.h"
20
21namespace agg
22{
23
24    // See Implementation agg_line_aa_basics.cpp
25
26    //-------------------------------------------------------------------------
27    enum line_subpixel_scale_e
28    {
29        line_subpixel_shift = 8,                          //----line_subpixel_shift
30        line_subpixel_scale  = 1 << line_subpixel_shift,  //----line_subpixel_scale
31        line_subpixel_mask  = line_subpixel_scale - 1,    //----line_subpixel_mask
32        line_max_coord      = (1 << 28) - 1,              //----line_max_coord
33        line_max_length = 1 << (line_subpixel_shift + 10) //----line_max_length
34    };
35
36    //-------------------------------------------------------------------------
37    enum line_mr_subpixel_scale_e
38    {
39        line_mr_subpixel_shift = 4,                           //----line_mr_subpixel_shift
40        line_mr_subpixel_scale = 1 << line_mr_subpixel_shift, //----line_mr_subpixel_scale
41        line_mr_subpixel_mask  = line_mr_subpixel_scale - 1   //----line_mr_subpixel_mask
42    };
43
44    //------------------------------------------------------------------line_mr
45    AGG_INLINE int line_mr(int x)
46    {
47        return x >> (line_subpixel_shift - line_mr_subpixel_shift);
48    }
49
50    //-------------------------------------------------------------------line_hr
51    AGG_INLINE int line_hr(int x)
52    {
53        return x << (line_subpixel_shift - line_mr_subpixel_shift);
54    }
55
56    //---------------------------------------------------------------line_dbl_hr
57    AGG_INLINE int line_dbl_hr(int x)
58    {
59        return x << line_subpixel_shift;
60    }
61
62    //---------------------------------------------------------------line_coord
63    struct line_coord
64    {
65        AGG_INLINE static int conv(double x)
66        {
67            return iround(x * line_subpixel_scale);
68        }
69    };
70
71    //-----------------------------------------------------------line_coord_sat
72    struct line_coord_sat
73    {
74        AGG_INLINE static int conv(double x)
75        {
76            return saturation<line_max_coord>::iround(x * line_subpixel_scale);
77        }
78    };
79
80    //==========================================================line_parameters
81    struct line_parameters
82    {
83        //---------------------------------------------------------------------
84        line_parameters() {}
85        line_parameters(int x1_, int y1_, int x2_, int y2_, int len_) :
86            x1(x1_), y1(y1_), x2(x2_), y2(y2_),
87            dx(abs(x2_ - x1_)),
88            dy(abs(y2_ - y1_)),
89            sx((x2_ > x1_) ? 1 : -1),
90            sy((y2_ > y1_) ? 1 : -1),
91            vertical(dy >= dx),
92            inc(vertical ? sy : sx),
93            len(len_),
94            octant((sy & 4) | (sx & 2) | int(vertical))
95        {
96        }
97
98        //---------------------------------------------------------------------
99        unsigned orthogonal_quadrant() const { return s_orthogonal_quadrant[octant]; }
100        unsigned diagonal_quadrant()   const { return s_diagonal_quadrant[octant];   }
101
102        //---------------------------------------------------------------------
103        bool same_orthogonal_quadrant(const line_parameters& lp) const
104        {
105            return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant];
106        }
107
108        //---------------------------------------------------------------------
109        bool same_diagonal_quadrant(const line_parameters& lp) const
110        {
111            return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant];
112        }
113
114        //---------------------------------------------------------------------
115        void divide(line_parameters& lp1, line_parameters& lp2) const
116        {
117            int xmid = (x1 + x2) >> 1;
118            int ymid = (y1 + y2) >> 1;
119            int len2 = len >> 1;
120
121            lp1 = *this;
122            lp2 = *this;
123
124            lp1.x2  = xmid;
125            lp1.y2  = ymid;
126            lp1.len = len2;
127            lp1.dx  = abs(lp1.x2 - lp1.x1);
128            lp1.dy  = abs(lp1.y2 - lp1.y1);
129
130            lp2.x1  = xmid;
131            lp2.y1  = ymid;
132            lp2.len = len2;
133            lp2.dx  = abs(lp2.x2 - lp2.x1);
134            lp2.dy  = abs(lp2.y2 - lp2.y1);
135        }
136
137        //---------------------------------------------------------------------
138        int x1, y1, x2, y2, dx, dy, sx, sy;
139        bool vertical;
140        int inc;
141        int len;
142        int octant;
143
144        //---------------------------------------------------------------------
145        static const int8u s_orthogonal_quadrant[8];
146        static const int8u s_diagonal_quadrant[8];
147    };
148
149
150
151    // See Implementation agg_line_aa_basics.cpp
152
153    //----------------------------------------------------------------bisectrix
154    void bisectrix(const line_parameters& l1,
155                   const line_parameters& l2,
156                   int* x, int* y);
157
158
159    //-------------------------------------------fix_degenerate_bisectrix_start
160    void inline fix_degenerate_bisectrix_start(const line_parameters& lp,
161                                               int* x, int* y)
162    {
163        int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
164                        double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
165        if(d < line_subpixel_scale/2)
166        {
167            *x = lp.x1 + (lp.y2 - lp.y1);
168            *y = lp.y1 - (lp.x2 - lp.x1);
169        }
170    }
171
172
173    //---------------------------------------------fix_degenerate_bisectrix_end
174    void inline fix_degenerate_bisectrix_end(const line_parameters& lp,
175                                             int* x, int* y)
176    {
177        int d = iround((double(*x - lp.x2) * double(lp.y2 - lp.y1) -
178                        double(*y - lp.y2) * double(lp.x2 - lp.x1)) / lp.len);
179        if(d < line_subpixel_scale/2)
180        {
181            *x = lp.x2 + (lp.y2 - lp.y1);
182            *y = lp.y2 - (lp.x2 - lp.x1);
183        }
184    }
185
186
187}
188
189#endif
190