1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /** @file
3  * TODO: insert short description here
4  *//*
5  * Authors: see git history
6  *
7  * Copyright (C) 2010 Authors
8  * Released under GNU GPL v2+, read the file 'COPYING' for more information.
9  */
10 #ifndef INKSCAPE_LIVAROT_FLOAT_LINE_H
11 #define INKSCAPE_LIVAROT_FLOAT_LINE_H
12 
13 /** \file
14  * Coverage with floating-point boundaries.
15  */
16 
17 #include <vector>
18 #include "livarot/LivarotDefs.h"
19 
20 class IntLigne;
21 
22 /// A coverage portion ("run") with floating point boundaries.
23 struct float_ligne_run {
24     float st;
25     float en;
26     float vst;
27     float ven;
28     float pente;   ///< (ven-vst)/(en-st)
29 };
30 
31 /**
32  * A floating-point boundary.
33  *
34  * Each float_ligne_bord is a boundary of some coverage.
35  * The Flatten() function will extract non-overlapping runs and produce an
36  * array of float_ligne_run. The float_ligne_bord are stored in an array, but
37  * linked like a doubly-linked list.
38  *
39  * The idea behind that is that a given edge produces one float_ligne_bord at
40  * the beginning of Scan() and possibly another in AvanceEdge() and
41  * DestroyEdge(); but that second float_ligne_bord will not be far away in
42  * the list from the first, so it's faster to salvage the index of the first
43  * float_ligne_bord and try to insert the second from that salvaged position.
44  */
45 struct float_ligne_bord {
46     float pos;    ///< position of the boundary
47     bool start;   ///< is the beginning of the coverage portion?
48     float val;    ///< amount of coverage (ie vst if start==true, and ven if start==false)
49     float pente;  ///< (ven-vst)/(en-st)
50     int other;    ///< index, in the array of float_ligne_bord, of the other boundary associated to this one
51     int s_prev;   ///< index of the previous bord in the doubly-linked list
52     int s_next;   ///< index of the next bord in the doubly-linked list
53     int pend_ind; ///< bords[i].pend_ind is the index of the float_ligne_bord that is the start of the
54                   ///< coverage portion being scanned (in the Flatten() )
55     int pend_inv; ///< inverse of pend_ind, for faster handling of insertion/removal in the "pending" array
56 };
57 
58 /**
59  * Coverage with floating-point boundaries.
60  *
61  * The goal is to salvage exact coverage info in the sweepline performed by
62  * Scan() or QuickScan(), then clean up a bit, convert floating point bounds
63  * to integer bounds, because pixel have integer bounds, and then raster runs
64  * of the type:
65  * \verbatim
66    position on the (pixel) line:                st         en
67                                                 |          |
68    coverage value (0=empty, 1=full)            vst   ->   ven   \endverbatim
69  */
70 class FloatLigne {
71 public:
72     std::vector<float_ligne_bord> bords; ///< vector of coverage boundaries
73     std::vector<float_ligne_run> runs;   ///< vector of runs
74 
75     /// first boundary in the doubly-linked list
76     int s_first;
77     /// last boundary in the doubly-linked list
78     int s_last;
79 
80     FloatLigne();
81     virtual ~FloatLigne();
82 
83     void Reset();
84 
85     int AddBord(float spos, float sval, float epos, float eval, int guess = -1);
86     int AddBord(float spos, float sval, float epos, float eval, float pente, int guess = -1);
87     int AddBordR(float spos, float sval, float epos, float eval, float pente, int guess = -1);
88     int AppendBord(float spos, float sval, float epos, float eval, float pente);
89 
90     void Flatten();
91 
92     void Affiche();
93 
94     void Max(FloatLigne *a, float tresh, bool addIt);
95 
96     void Min(FloatLigne *a, float tresh, bool addIt);
97 
98     void Split(FloatLigne *a, float tresh, FloatLigne *over);
99 
100     void Over(FloatLigne *a, float tresh);
101 
102     void Copy(IntLigne *a);
103     void Copy(FloatLigne *a);
104 
105     float RemainingValAt(float at, int pending);
106 
CmpBord(float_ligne_bord const & d1,float_ligne_bord const & d2)107     static int CmpBord(float_ligne_bord const &d1, float_ligne_bord const &d2) {
108         if ( d1.pos == d2.pos ) {
109             if ( d1.start && !(d2.start) ) {
110                 return 1;
111             }
112             if ( !(d1.start) && d2.start ) {
113                 return -1;
114             }
115             return 0;
116         }
117 
118         return (( d1.pos < d2.pos ) ? -1 : 1);
119     };
120 
121     int AddRun(float st, float en, float vst, float ven, float pente);
122 
123 private:
124     void InsertBord(int no, float p, int guess);
125     int AddRun(float st, float en, float vst, float ven);
126 
ValAt(float at,float ps,float pe,float vs,float ve)127     inline float ValAt(float at, float ps, float pe, float vs, float ve) {
128         return ((at - ps) * ve + (pe - at) * vs) / (pe - ps);
129     };
130 };
131 
132 #endif
133 
134 
135 /*
136   Local Variables:
137   mode:c++
138   c-file-style:"stroustrup"
139   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
140   indent-tabs-mode:nil
141   fill-column:99
142   End:
143 */
144 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
145