1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
|
// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2010, SIL International, All rights reserved.
#pragma once
#include <utility>
#include "inc/Main.h"
#include "inc/List.h"
#include "inc/json.h"
#include "inc/Position.h"
// An IntervalSet represents the possible movement of a given glyph in a given direction
// (horizontally, vertically, or diagonally).
// A vector is needed to represent disjoint ranges, eg, -300..-150, 20..200, 500..750.
// Each pair represents the min/max of a sub-range.
namespace graphite2 {
class Segment;
enum zones_t {SD, XY};
class Zones
{
struct Exclusion
{
template<zones_t O>
static Exclusion weighted(float xmin, float xmax, float f, float a0,
float m, float xi, float ai, float c, bool nega);
float x, // x position
xm, // xmax position
c, // constant + sum(MiXi^2)
sm, // sum(Mi)
smx; // sum(MiXi)
bool open;
Exclusion(float x, float w, float smi, float smxi, float c);
Exclusion & operator += (Exclusion const & rhs);
uint8 outcode(float p) const;
Exclusion split_at(float p);
void left_trim(float p);
bool track_cost(float & cost, float & x, float origin) const;
private:
float test_position(float origin) const;
float cost(float x) const;
};
typedef Vector<Exclusion> exclusions;
typedef exclusions::iterator iterator;
typedef Exclusion * pointer;
typedef Exclusion & reference;
typedef std::reverse_iterator<iterator> reverse_iterator;
public:
typedef exclusions::const_iterator const_iterator;
typedef Exclusion const * const_pointer;
typedef Exclusion const & const_reference;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
#if !defined GRAPHITE2_NTRACING
struct Debug
{
Exclusion _excl;
bool _isdel;
Vector<void *> _env;
Debug(Exclusion *e, bool isdel, json *dbg) : _excl(*e), _isdel(isdel), _env(dbg->getenvs()) { };
};
typedef Vector<Debug> debugs;
typedef debugs::const_iterator idebugs;
void addDebug(Exclusion *e);
void removeDebug(float pos, float posm);
void setdebug(json *dbgout) { _dbg = dbgout; }
idebugs dbgs_begin() const { return _dbgs.begin(); }
idebugs dbgs_end() const { return _dbgs.end(); }
void jsonDbgOut(Segment *seg) const;
Position position() const { return Position(_pos, _posm); }
#endif
Zones();
template<zones_t O>
void initialise(float xmin, float xmax, float margin_len, float margin_weight, float ao);
void exclude(float xmin, float xmax);
void exclude_with_margins(float xmin, float xmax, int axis);
template<zones_t O>
void weighted(float xmin, float xmax, float f, float a0, float mi, float xi, float ai, float c, bool nega);
void weightedAxis(int axis, float xmin, float xmax, float f, float a0, float mi, float xi, float ai, float c, bool nega);
float closest( float origin, float &cost) const;
const_iterator begin() const { return _exclusions.begin(); }
const_iterator end() const { return _exclusions.end(); }
private:
exclusions _exclusions;
#if !defined GRAPHITE2_NTRACING
json * _dbg;
debugs _dbgs;
#endif
float _margin_len,
_margin_weight,
_pos,
_posm;
void insert(Exclusion e);
void remove(float x, float xm);
const_iterator find_exclusion_under(float x) const;
};
inline
Zones::Zones()
: _margin_len(0), _margin_weight(0), _pos(0), _posm(0)
{
#if !defined GRAPHITE2_NTRACING
_dbg = 0;
#endif
_exclusions.reserve(8);
}
inline
Zones::Exclusion::Exclusion(float x_, float xm_, float smi, float smxi, float c_)
: x(x_), xm(xm_), c(c_), sm(smi), smx(smxi), open(false)
{ }
template<zones_t O>
inline
void Zones::initialise(float xmin, float xmax, float margin_len,
float margin_weight, float a0)
{
_margin_len = margin_len;
_margin_weight = margin_weight;
_pos = xmin;
_posm = xmax;
_exclusions.clear();
_exclusions.push_back(Exclusion::weighted<O>(xmin, xmax, 1, a0, 0, 0, 0, 0, false));
_exclusions.front().open = true;
#if !defined GRAPHITE2_NTRACING
_dbgs.clear();
#endif
}
inline
void Zones::exclude(float xmin, float xmax) {
remove(xmin, xmax);
}
template<zones_t O>
inline
void Zones::weighted(float xmin, float xmax, float f, float a0,
float m, float xi, float ai, float c, bool nega) {
insert(Exclusion::weighted<O>(xmin, xmax, f, a0, m, xi, ai, c, nega));
}
inline
void Zones::weightedAxis(int axis, float xmin, float xmax, float f, float a0,
float m, float xi, float ai, float c, bool nega) {
if (axis < 2)
weighted<XY>(xmin, xmax, f, a0, m, xi, ai, c, nega);
else
weighted<SD>(xmin, xmax, f, a0, m, xi, ai, c, nega);
}
#if !defined GRAPHITE2_NTRACING
inline
void Zones::addDebug(Exclusion *e) {
if (_dbg)
_dbgs.push_back(Debug(e, false, _dbg));
}
inline
void Zones::removeDebug(float pos, float posm) {
if (_dbg)
{
Exclusion e(pos, posm, 0, 0, 0);
_dbgs.push_back(Debug(&e, true, _dbg));
}
}
#endif
template<>
inline
Zones::Exclusion Zones::Exclusion::weighted<XY>(float xmin, float xmax, float f, float a0,
float m, float xi, GR_MAYBE_UNUSED float ai, float c, GR_MAYBE_UNUSED bool nega) {
return Exclusion(xmin, xmax,
m + f,
m * xi,
m * xi * xi + f * a0 * a0 + c);
}
template<>
inline
Zones::Exclusion Zones::Exclusion::weighted<SD>(float xmin, float xmax, float f, float a0,
float m, float xi, float ai,float c, bool nega) {
float xia = nega ? xi - ai : xi + ai;
return Exclusion(xmin, xmax,
0.25f * (m + 2.f * f),
0.25f * m * xia,
0.25f * (m * xia * xia + 2.f * f * a0 * a0) + c);
}
} // end of namespace graphite2
|