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 "inc/List.h"
30 #include "inc/Position.h"
31 #include "inc/Intervals.h"
32 #include "inc/debug.h"
33
34 namespace graphite2 {
35
36 class json;
37 class Slot;
38 class Segment;
39
40 #define SLOTCOLSETUINTPROP(x, y) uint16 x() const { return _ ##x; } void y (uint16 v) { _ ##x = v; }
41 #define SLOTCOLSETINTPROP(x, y) int16 x() const { return _ ##x; } void y (int16 v) { _ ##x = v; }
42 #define SLOTCOLSETPOSITIONPROP(x, y) const Position &x() const { return _ ##x; } void y (const Position &v) { _ ##x = v; }
43
44 // Slot attributes related to collision-fixing
45 class SlotCollision
46 {
47 public:
48 enum {
49 // COLL_TESTONLY = 0, // default - test other glyphs for collision with this one, but don't move this one
50 COLL_FIX = 1, // fix collisions involving this glyph
51 COLL_IGNORE = 2, // ignore this glyph altogether
52 COLL_START = 4, // start of range of possible collisions
53 COLL_END = 8, // end of range of possible collisions
54 COLL_KERN = 16, // collisions with this glyph are fixed by adding kerning space after it
55 COLL_ISCOL = 32, // this glyph has a collision
56 COLL_KNOWN = 64, // we've figured out what's happening with this glyph
57 COLL_ISSPACE = 128, // treat this glyph as a space with regard to kerning
58 COLL_TEMPLOCK = 256, // Lock glyphs that have been given priority positioning
59 ////COLL_JUMPABLE = 128, // moving glyphs may jump this stationary glyph in any direction - DELETE
60 ////COLL_OVERLAP = 256, // use maxoverlap to restrict - DELETE
61 };
62
63 // Behavior for the collision.order attribute. To GDL this is an enum, to us it's a bitfield, with only 1 bit set
64 // Allows for easier inversion.
65 enum {
66 SEQ_ORDER_LEFTDOWN = 1,
67 SEQ_ORDER_RIGHTUP = 2,
68 SEQ_ORDER_NOABOVE = 4,
69 SEQ_ORDER_NOBELOW = 8,
70 SEQ_ORDER_NOLEFT = 16,
71 SEQ_ORDER_NORIGHT = 32
72 };
73
74 SlotCollision(Segment *seg, Slot *slot);
75 void initFromSlot(Segment *seg, Slot *slot);
76
limit()77 const Rect &limit() const { return _limit; }
setLimit(const Rect & r)78 void setLimit(const Rect &r) { _limit = r; }
79 SLOTCOLSETPOSITIONPROP(shift, setShift)
80 SLOTCOLSETPOSITIONPROP(offset, setOffset)
81 SLOTCOLSETPOSITIONPROP(exclOffset, setExclOffset)
82 SLOTCOLSETUINTPROP(margin, setMargin)
83 SLOTCOLSETUINTPROP(marginWt, setMarginWt)
84 SLOTCOLSETUINTPROP(flags, setFlags)
85 SLOTCOLSETUINTPROP(exclGlyph, setExclGlyph)
86 SLOTCOLSETUINTPROP(seqClass, setSeqClass)
87 SLOTCOLSETUINTPROP(seqProxClass, setSeqProxClass)
88 SLOTCOLSETUINTPROP(seqOrder, setSeqOrder)
89 SLOTCOLSETINTPROP(seqAboveXoff, setSeqAboveXoff)
90 SLOTCOLSETUINTPROP(seqAboveWt, setSeqAboveWt)
91 SLOTCOLSETINTPROP(seqBelowXlim, setSeqBelowXlim)
92 SLOTCOLSETUINTPROP(seqBelowWt, setSeqBelowWt)
93 SLOTCOLSETUINTPROP(seqValignHt, setSeqValignHt)
94 SLOTCOLSETUINTPROP(seqValignWt, setSeqValignWt)
95
96 float getKern(int dir) const;
97 bool ignore() const;
98
99 private:
100 Rect _limit;
101 Position _shift; // adjustment within the given pass
102 Position _offset; // total adjustment for collisions
103 Position _exclOffset;
104 uint16 _margin;
105 uint16 _marginWt;
106 uint16 _flags;
107 uint16 _exclGlyph;
108 uint16 _seqClass;
109 uint16 _seqProxClass;
110 uint16 _seqOrder;
111 int16 _seqAboveXoff;
112 uint16 _seqAboveWt;
113 int16 _seqBelowXlim;
114 uint16 _seqBelowWt;
115 uint16 _seqValignHt;
116 uint16 _seqValignWt;
117
118 }; // end of class SlotColllision
119
120 struct BBox;
121 struct SlantBox;
122
123 class ShiftCollider
124 {
125 public:
126 typedef std::pair<float, float> fpair;
127 typedef Vector<fpair> vfpairs;
128 typedef vfpairs::iterator ivfpairs;
129
130 ShiftCollider(json *dbgout);
throw()131 ~ShiftCollider() throw() { };
132
133 bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint,
134 float margin, float marginMin, const Position &currShift,
135 const Position &currOffset, int dir, GR_MAYBE_UNUSED json * const dbgout);
136 bool mergeSlot(Segment *seg, Slot *slot, const SlotCollision *cinfo, const Position &currShift, bool isAfter,
137 bool sameCluster, bool &hasCol, bool isExclusion, GR_MAYBE_UNUSED json * const dbgout);
138 Position resolve(Segment *seg, bool &isCol, GR_MAYBE_UNUSED json * const dbgout);
139 void addBox_slope(bool isx, const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, float weight, float m, bool minright, int mode);
140 void removeBox(const Rect &box, const BBox &bb, const SlantBox &sb, const Position &org, int mode);
origin()141 const Position &origin() const { return _origin; }
142
143 #if !defined GRAPHITE2_NTRACING
144 void outputJsonDbg(json * const dbgout, Segment *seg, int axis);
145 void outputJsonDbgStartSlot(json * const dbgout, Segment *seg);
146 void outputJsonDbgEndSlot(json * const dbgout, Position resultPos, int bestAxis, bool isCol);
147 void outputJsonDbgOneVector(json * const dbgout, Segment *seg, int axis, float tleft, float bestCost, float bestVal);
148 void outputJsonDbgRawRanges(json * const dbgout, int axis);
149 void outputJsonDbgRemovals(json * const dbgout, int axis, Segment *seg);
150 #endif
151
152 CLASS_NEW_DELETE;
153
154 protected:
155 Zones _ranges[4]; // possible movements in 4 directions (horizontally, vertically, diagonally);
156 Slot * _target; // the glyph to fix
157 Rect _limit;
158 Position _currShift;
159 Position _currOffset;
160 Position _origin; // Base for all relative calculations
161 float _margin;
162 float _marginWt;
163 float _len[4];
164 uint16 _seqClass;
165 uint16 _seqProxClass;
166 uint16 _seqOrder;
167
168 //bool _scraping[4];
169
170 }; // end of class ShiftCollider
171
172 inline
ShiftCollider(GR_MAYBE_UNUSED json * dbgout)173 ShiftCollider::ShiftCollider(GR_MAYBE_UNUSED json *dbgout)
174 : _target(0),
175 _margin(0.0),
176 _marginWt(0.0),
177 _seqClass(0),
178 _seqProxClass(0),
179 _seqOrder(0)
180 {
181 #if !defined GRAPHITE2_NTRACING
182 for (int i = 0; i < 4; ++i)
183 _ranges[i].setdebug(dbgout);
184 #endif
185 }
186
187 class KernCollider
188 {
189 public:
190 KernCollider(json *dbg);
throw()191 ~KernCollider() throw() { };
192 bool initSlot(Segment *seg, Slot *aSlot, const Rect &constraint, float margin,
193 const Position &currShift, const Position &offsetPrev, int dir,
194 float ymin, float ymax, json * const dbgout);
195 bool mergeSlot(Segment *seg, Slot *slot, const Position &currShift, float currSpace, int dir, json * const dbgout);
196 Position resolve(Segment *seg, Slot *slot, int dir, json * const dbgout);
197 void shift(const Position &mv, int dir);
198
199 CLASS_NEW_DELETE;
200
201 private:
202 Slot * _target; // the glyph to fix
203 Rect _limit;
204 float _margin;
205 Position _offsetPrev; // kern from a previous pass
206 Position _currShift; // NOT USED??
207 float _miny; // y-coordinates offset by global slot position
208 float _maxy;
209 Vector<float> _edges; // edges of horizontal slices
210 float _sliceWidth; // width of each slice
211 float _mingap;
212 float _xbound; // max or min edge
213 bool _hit;
214
215 #if !defined GRAPHITE2_NTRACING
216 // Debugging
217 Segment * _seg;
218 Vector<float> _nearEdges; // closest potential collision in each slice
219 Vector<Slot*> _slotNear;
220 #endif
221 }; // end of class KernCollider
222
223
224 inline
sqr(float x)225 float sqr(float x) {
226 return x * x;
227 }
228
229 inline
KernCollider(GR_MAYBE_UNUSED json * dbg)230 KernCollider::KernCollider(GR_MAYBE_UNUSED json *dbg)
231 : _target(0),
232 _margin(0.0f),
233 _miny(-1e38f),
234 _maxy(1e38f),
235 _sliceWidth(0.0f),
236 _mingap(0.0f),
237 _xbound(0.0),
238 _hit(false)
239 {
240 #if !defined GRAPHITE2_NTRACING
241 _seg = 0;
242 #endif
243 };
244
245 }; // end of namespace graphite2
246