Intervals.h (7334B)
1 /* GRAPHITE2 LICENSING 2 3 Copyright 2010, SIL International 4 All rights reserved. 5 6 This library is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as published 8 by the Free Software Foundation; either version 2.1 of License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should also have received a copy of the GNU Lesser General Public 17 License along with this library in the file named "LICENSE". 18 If not, write to the Free Software Foundation, 51 Franklin Street, 19 Suite 500, Boston, MA 02110-1335, USA or visit their web page on the 20 internet at http://www.fsf.org/licenses/lgpl.html. 21 22 Alternatively, the contents of this file may be used under the terms of the 23 Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public 24 License, as published by the Free Software Foundation, either version 2 25 of the License or (at your option) any later version. 26 */ 27 #pragma once 28 29 #include <utility> 30 31 #include "inc/Main.h" 32 #include "inc/List.h" 33 #include "inc/json.h" 34 #include "inc/Position.h" 35 36 // An IntervalSet represents the possible movement of a given glyph in a given direction 37 // (horizontally, vertically, or diagonally). 38 // A vector is needed to represent disjoint ranges, eg, -300..-150, 20..200, 500..750. 39 // Each pair represents the min/max of a sub-range. 40 41 namespace graphite2 { 42 43 class Segment; 44 45 enum zones_t {SD, XY}; 46 47 class Zones 48 { 49 struct Exclusion 50 { 51 template<zones_t O> 52 static Exclusion weighted(float xmin, float xmax, float f, float a0, 53 float m, float xi, float ai, float c, bool nega); 54 55 float x, // x position 56 xm, // xmax position 57 c, // constant + sum(MiXi^2) 58 sm, // sum(Mi) 59 smx; // sum(MiXi) 60 bool open; 61 62 Exclusion(float x, float w, float smi, float smxi, float c); 63 Exclusion & operator += (Exclusion const & rhs); 64 uint8 outcode(float p) const; 65 66 Exclusion split_at(float p); 67 void left_trim(float p); 68 69 bool track_cost(float & cost, float & x, float origin) const; 70 71 private: 72 float test_position(float origin) const; 73 float cost(float x) const; 74 }; 75 76 typedef Vector<Exclusion> exclusions; 77 78 typedef exclusions::iterator iterator; 79 typedef Exclusion * pointer; 80 typedef Exclusion & reference; 81 typedef std::reverse_iterator<iterator> reverse_iterator; 82 83 public: 84 typedef exclusions::const_iterator const_iterator; 85 typedef Exclusion const * const_pointer; 86 typedef Exclusion const & const_reference; 87 typedef std::reverse_iterator<const_iterator> const_reverse_iterator; 88 89 #if !defined GRAPHITE2_NTRACING 90 struct Debug 91 { 92 Exclusion _excl; 93 bool _isdel; 94 Vector<void *> _env; 95 96 Debug(Exclusion *e, bool isdel, json *dbg) : _excl(*e), _isdel(isdel), _env(dbg->getenvs()) { }; 97 }; 98 99 typedef Vector<Debug> debugs; 100 typedef debugs::const_iterator idebugs; 101 void addDebug(Exclusion *e); 102 void removeDebug(float pos, float posm); 103 void setdebug(json *dbgout) { _dbg = dbgout; } 104 idebugs dbgs_begin() const { return _dbgs.begin(); } 105 idebugs dbgs_end() const { return _dbgs.end(); } 106 void jsonDbgOut(Segment *seg) const; 107 Position position() const { return Position(_pos, _posm); } 108 #endif 109 110 Zones(); 111 template<zones_t O> 112 void initialise(float xmin, float xmax, float margin_len, float margin_weight, float ao); 113 114 void exclude(float xmin, float xmax); 115 void exclude_with_margins(float xmin, float xmax, int axis); 116 117 template<zones_t O> 118 void weighted(float xmin, float xmax, float f, float a0, float mi, float xi, float ai, float c, bool nega); 119 void weightedAxis(int axis, float xmin, float xmax, float f, float a0, float mi, float xi, float ai, float c, bool nega); 120 121 float closest( float origin, float &cost) const; 122 123 const_iterator begin() const { return _exclusions.begin(); } 124 const_iterator end() const { return _exclusions.end(); } 125 126 private: 127 exclusions _exclusions; 128 #if !defined GRAPHITE2_NTRACING 129 json * _dbg; 130 debugs _dbgs; 131 #endif 132 float _margin_len, 133 _margin_weight, 134 _pos, 135 _posm; 136 137 void insert(Exclusion e); 138 void remove(float x, float xm); 139 const_iterator find_exclusion_under(float x) const; 140 }; 141 142 143 inline 144 Zones::Zones() 145 : _margin_len(0), _margin_weight(0), _pos(0), _posm(0) 146 { 147 #if !defined GRAPHITE2_NTRACING 148 _dbg = 0; 149 #endif 150 _exclusions.reserve(8); 151 } 152 153 inline 154 Zones::Exclusion::Exclusion(float x_, float xm_, float smi, float smxi, float c_) 155 : x(x_), xm(xm_), c(c_), sm(smi), smx(smxi), open(false) 156 { } 157 158 template<zones_t O> 159 inline 160 void Zones::initialise(float xmin, float xmax, float margin_len, 161 float margin_weight, float a0) 162 { 163 _margin_len = margin_len; 164 _margin_weight = margin_weight; 165 _pos = xmin; 166 _posm = xmax; 167 _exclusions.clear(); 168 _exclusions.push_back(Exclusion::weighted<O>(xmin, xmax, 1, a0, 0, 0, 0, 0, false)); 169 _exclusions.front().open = true; 170 #if !defined GRAPHITE2_NTRACING 171 _dbgs.clear(); 172 #endif 173 } 174 175 inline 176 void Zones::exclude(float xmin, float xmax) { 177 remove(xmin, xmax); 178 } 179 180 template<zones_t O> 181 inline 182 void Zones::weighted(float xmin, float xmax, float f, float a0, 183 float m, float xi, float ai, float c, bool nega) { 184 insert(Exclusion::weighted<O>(xmin, xmax, f, a0, m, xi, ai, c, nega)); 185 } 186 187 inline 188 void Zones::weightedAxis(int axis, float xmin, float xmax, float f, float a0, 189 float m, float xi, float ai, float c, bool nega) { 190 if (axis < 2) 191 weighted<XY>(xmin, xmax, f, a0, m, xi, ai, c, nega); 192 else 193 weighted<SD>(xmin, xmax, f, a0, m, xi, ai, c, nega); 194 } 195 196 #if !defined GRAPHITE2_NTRACING 197 inline 198 void Zones::addDebug(Exclusion *e) { 199 if (_dbg) 200 _dbgs.push_back(Debug(e, false, _dbg)); 201 } 202 203 inline 204 void Zones::removeDebug(float pos, float posm) { 205 if (_dbg) 206 { 207 Exclusion e(pos, posm, 0, 0, 0); 208 _dbgs.push_back(Debug(&e, true, _dbg)); 209 } 210 } 211 #endif 212 213 template<> 214 inline 215 Zones::Exclusion Zones::Exclusion::weighted<XY>(float xmin, float xmax, float f, float a0, 216 float m, float xi, GR_MAYBE_UNUSED float ai, float c, GR_MAYBE_UNUSED bool nega) { 217 return Exclusion(xmin, xmax, 218 m + f, 219 m * xi, 220 m * xi * xi + f * a0 * a0 + c); 221 } 222 223 template<> 224 inline 225 Zones::Exclusion Zones::Exclusion::weighted<SD>(float xmin, float xmax, float f, float a0, 226 float m, float xi, float ai,float c, bool nega) { 227 float xia = nega ? xi - ai : xi + ai; 228 return Exclusion(xmin, xmax, 229 0.25f * (m + 2.f * f), 230 0.25f * m * xia, 231 0.25f * (m * xia * xia + 2.f * f * a0 * a0) + c); 232 } 233 234 } // end of namespace graphite2