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 : #include "inc/Segment.h"
28 : #include "inc/Slot.h"
29 : #include "inc/CharInfo.h"
30 : #include "inc/Rule.h"
31 :
32 :
33 : using namespace graphite2;
34 :
35 0 : Slot::Slot() :
36 : m_next(NULL), m_prev(NULL),
37 : m_glyphid(0), m_realglyphid(0), m_original(0), m_before(0), m_after(0),
38 : m_parent(NULL), m_child(NULL), m_sibling(NULL),
39 : m_position(0, 0), m_shift(0, 0), m_advance(-1, -1),
40 : m_attach(0, 0), m_with(0, 0), m_just(0.),
41 0 : m_flags(0), m_attLevel(0)
42 : // Do not set m_userAttr since it is set *before* new is called since this
43 : // is used as a positional new to reset the GrSlot
44 : {
45 0 : }
46 :
47 : // take care, this does not copy any of the GrSlot pointer fields
48 0 : void Slot::set(const Slot & orig, int charOffset, uint8 numUserAttr)
49 : {
50 : // leave m_next and m_prev unchanged
51 0 : m_glyphid = orig.m_glyphid;
52 0 : m_realglyphid = orig.m_realglyphid;
53 0 : m_original = orig.m_original + charOffset;
54 0 : m_before = orig.m_before + charOffset;
55 0 : m_after = orig.m_after + charOffset;
56 0 : m_parent = NULL;
57 0 : m_child = NULL;
58 0 : m_sibling = NULL;
59 0 : m_position = orig.m_position;
60 0 : m_shift = orig.m_shift;
61 0 : m_advance = orig.m_advance;
62 0 : m_attach = orig.m_attach;
63 0 : m_with = orig.m_with;
64 0 : m_flags = orig.m_flags;
65 0 : m_attLevel = orig.m_attLevel;
66 0 : assert(!orig.m_userAttr || m_userAttr);
67 0 : if (m_userAttr && orig.m_userAttr)
68 : {
69 0 : memcpy(m_userAttr, orig.m_userAttr, numUserAttr * sizeof(*m_userAttr));
70 : }
71 0 : }
72 :
73 0 : void Slot::update(int /*numGrSlots*/, int numCharInfo, Position &relpos)
74 : {
75 0 : m_before += numCharInfo;
76 0 : m_after += numCharInfo;
77 0 : m_position = m_position + relpos;
78 0 : }
79 :
80 0 : Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, float & cMin, uint8 attrLevel, float & clusterMin)
81 : {
82 0 : if (attrLevel && m_attLevel > attrLevel) return Position(0, 0);
83 0 : float scale = 1.0;
84 0 : Position shift = m_shift + Position(m_just, 0);
85 0 : float tAdvance = m_advance.x + m_just;
86 0 : const GlyphFace * glyphFace = seg->getFace()->getGlyphFaceCache()->glyphSafe(glyph());
87 0 : if (font)
88 : {
89 0 : scale = font->scale();
90 0 : shift *= scale;
91 0 : if (font->isHinted())
92 : {
93 0 : if (glyphFace)
94 0 : tAdvance = (m_advance.x - glyphFace->theAdvance().x) * scale + font->advance(m_glyphid);
95 : else
96 0 : tAdvance = (m_advance.x - seg->glyphAdvance(glyph())) * scale + font->advance(m_glyphid);
97 : }
98 : else
99 0 : tAdvance *= scale;
100 : }
101 0 : Position res;
102 :
103 0 : m_position = base + shift;
104 0 : if (!m_parent)
105 : {
106 0 : res = base + Position(tAdvance, m_advance.y * scale);
107 0 : cMin = 0.;
108 0 : clusterMin = base.x;
109 : }
110 : else
111 : {
112 : float tAdv;
113 0 : m_position += (m_attach - m_with) * scale;
114 0 : tAdv = tAdvance > 0.f ? m_position.x + tAdvance - shift.x : 0.f;
115 0 : res = Position(tAdv, 0);
116 0 : if (m_position.x < clusterMin) clusterMin = m_position.x;
117 : }
118 :
119 0 : if (glyphFace)
120 : {
121 0 : Rect ourBbox = glyphFace->theBBox() * scale + m_position;
122 0 : bbox = bbox.widen(ourBbox);
123 : }
124 : //Rect ourBbox = seg->theGlyphBBoxTemporary(glyph()) * scale + m_position;
125 : //bbox->widen(ourBbox);
126 :
127 0 : if (m_parent && m_position.x < cMin) cMin = m_position.x;
128 :
129 0 : if (m_child && m_child != this && m_child->attachedTo() == this)
130 : {
131 0 : Position tRes = m_child->finalise(seg, font, m_position, bbox, cMin, attrLevel, clusterMin);
132 0 : if (tRes.x > res.x) res = tRes;
133 : }
134 :
135 0 : if (m_parent && m_sibling && m_sibling != this && m_sibling->attachedTo() == m_parent)
136 : {
137 0 : Position tRes = m_sibling->finalise(seg, font, base, bbox, cMin, attrLevel, clusterMin);
138 0 : if (tRes.x > res.x) res = tRes;
139 : }
140 :
141 0 : if (!m_parent)
142 : {
143 0 : if (cMin < 0)
144 : {
145 0 : Position adj = Position(-cMin, 0.);
146 0 : res += adj;
147 0 : m_position += adj;
148 0 : if (m_child) m_child->floodShift(adj);
149 : }
150 0 : else if ((seg->dir() & 1) && (clusterMin < base.x))
151 : {
152 0 : Position adj = Position(base.x - clusterMin, 0.);
153 0 : res += adj;
154 0 : m_position += adj;
155 0 : if (m_child) m_child->floodShift(adj);
156 : }
157 : }
158 0 : return res;
159 : }
160 :
161 0 : uint32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel)
162 : {
163 0 : Position base;
164 0 : Rect bbox = seg->theGlyphBBoxTemporary(gid());
165 0 : float cMin = 0.;
166 0 : float clusterMin = 0.;
167 0 : Position res = finalise(seg, NULL, base, bbox, cMin, attrLevel, clusterMin);
168 :
169 0 : switch (metrics(metric))
170 : {
171 : case kgmetLsb :
172 0 : return static_cast<uint32>(bbox.bl.x);
173 : case kgmetRsb :
174 0 : return static_cast<uint32>(res.x - bbox.tr.x);
175 : case kgmetBbTop :
176 0 : return static_cast<uint32>(bbox.tr.y);
177 : case kgmetBbBottom :
178 0 : return static_cast<uint32>(bbox.bl.y);
179 : case kgmetBbLeft :
180 0 : return static_cast<uint32>(bbox.bl.x);
181 : case kgmetBbRight :
182 0 : return static_cast<uint32>(bbox.tr.x);
183 : case kgmetBbWidth :
184 0 : return static_cast<uint32>(bbox.tr.x - bbox.bl.x);
185 : case kgmetBbHeight :
186 0 : return static_cast<uint32>(bbox.tr.y - bbox.bl.y);
187 : case kgmetAdvWidth :
188 0 : return static_cast<uint32>(res.x);
189 : case kgmetAdvHeight :
190 0 : return static_cast<uint32>(res.y);
191 : default :
192 0 : return 0;
193 : }
194 : }
195 :
196 0 : int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
197 : {
198 0 : if (!this) return 0;
199 0 : if (ind == gr_slatUserDefnV1)
200 : {
201 0 : ind = gr_slatUserDefn;
202 0 : subindex = 0;
203 : }
204 0 : switch (ind)
205 : {
206 0 : case gr_slatAdvX : return int(m_advance.x);
207 0 : case gr_slatAdvY : return int(m_advance.y);
208 0 : case gr_slatAttTo : return 0;
209 0 : case gr_slatAttX : return int(m_attach.x);
210 0 : case gr_slatAttY : return int(m_attach.y);
211 : case gr_slatAttXOff :
212 0 : case gr_slatAttYOff : return 0;
213 0 : case gr_slatAttWithX : return int(m_with.x);
214 0 : case gr_slatAttWithY : return int(m_with.y);
215 : case gr_slatAttWithXOff:
216 0 : case gr_slatAttWithYOff:return 0;
217 0 : case gr_slatAttLevel : return m_attLevel;
218 0 : case gr_slatBreak : return seg->charinfo(m_original)->breakWeight();
219 0 : case gr_slatCompRef : return 0;
220 0 : case gr_slatDir : return seg->dir();
221 0 : case gr_slatInsert : return isInsertBefore();
222 0 : case gr_slatPosX : return int(m_position.x); // but need to calculate it
223 0 : case gr_slatPosY : return int(m_position.y);
224 0 : case gr_slatShiftX : return int(m_shift.x);
225 0 : case gr_slatShiftY : return int(m_shift.y);
226 0 : case gr_slatMeasureSol: return -1; // err what's this?
227 0 : case gr_slatMeasureEol: return -1;
228 : case gr_slatJStretch :
229 : case gr_slatJShrink :
230 : case gr_slatJStep :
231 0 : case gr_slatJWeight : return 0;
232 0 : case gr_slatJWidth : return m_just;
233 0 : case gr_slatUserDefn : return m_userAttr[subindex];
234 0 : default : return 0;
235 : }
236 : }
237 :
238 0 : void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, const SlotMap & map)
239 : {
240 0 : if (!this) return;
241 0 : if (ind == gr_slatUserDefnV1)
242 : {
243 0 : ind = gr_slatUserDefn;
244 0 : subindex = 0;
245 : }
246 0 : switch (ind)
247 : {
248 0 : case gr_slatAdvX : m_advance.x = value; break;
249 0 : case gr_slatAdvY : m_advance.y = value; break;
250 : case gr_slatAttTo :
251 : {
252 0 : const uint16 idx = uint16(value);
253 0 : if (idx < map.size() && map[idx])
254 : {
255 0 : Slot *other = map[idx];
256 0 : if (other != this && other->child(this))
257 : {
258 0 : attachTo(other);
259 0 : m_attach = Position(seg->glyphAdvance(other->gid()), 0);
260 : }
261 : }
262 0 : break;
263 : }
264 0 : case gr_slatAttX : m_attach.x = value; break;
265 0 : case gr_slatAttY : m_attach.y = value; break;
266 : case gr_slatAttXOff :
267 0 : case gr_slatAttYOff : break;
268 0 : case gr_slatAttWithX : m_with.x = value; break;
269 0 : case gr_slatAttWithY : m_with.y = value; break;
270 : case gr_slatAttWithXOff :
271 0 : case gr_slatAttWithYOff : break;
272 : case gr_slatAttLevel :
273 0 : m_attLevel = byte(value);
274 0 : break;
275 : case gr_slatBreak :
276 0 : seg->charinfo(m_original)->breakWeight(value);
277 0 : break;
278 0 : case gr_slatCompRef : break; // not sure what to do here
279 0 : case gr_slatDir : break; // read only
280 : case gr_slatInsert :
281 0 : markInsertBefore(value? true : false);
282 0 : break;
283 0 : case gr_slatPosX : break; // can't set these here
284 0 : case gr_slatPosY : break;
285 0 : case gr_slatShiftX : m_shift.x = value; break;
286 0 : case gr_slatShiftY : m_shift.y = value; break;
287 0 : case gr_slatMeasureSol : break;
288 0 : case gr_slatMeasureEol : break;
289 0 : case gr_slatJStretch : break; // handle these later
290 0 : case gr_slatJShrink : break;
291 0 : case gr_slatJStep : break;
292 0 : case gr_slatJWeight : break;
293 0 : case gr_slatJWidth : m_just = value; break;
294 0 : case gr_slatUserDefn : m_userAttr[subindex] = value; break;
295 : default :
296 0 : break;
297 : }
298 : }
299 :
300 0 : bool Slot::child(Slot *ap)
301 : {
302 0 : if (this == ap) return false;
303 0 : else if (ap == m_child) return true;
304 0 : else if (!m_child)
305 0 : m_child = ap;
306 : else
307 0 : return m_child->sibling(ap);
308 0 : return true;
309 : }
310 :
311 0 : bool Slot::sibling(Slot *ap)
312 : {
313 0 : if (this == ap) return false;
314 0 : else if (ap == m_sibling) return true;
315 0 : else if (!m_sibling || !ap)
316 0 : m_sibling = ap;
317 : else
318 0 : return m_sibling->sibling(ap);
319 0 : return true;
320 : }
321 :
322 0 : void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
323 : {
324 0 : m_glyphid = glyphid;
325 0 : if (!theGlyph)
326 : {
327 0 : theGlyph = seg->getFace()->getGlyphFaceCache()->glyphSafe(glyphid);
328 0 : if (!theGlyph)
329 : {
330 0 : m_realglyphid = 0;
331 0 : m_advance = Position(0.,0.);
332 0 : return;
333 : }
334 : }
335 0 : m_realglyphid = theGlyph->getAttr(seg->silf()->aPseudo());
336 0 : if (m_realglyphid)
337 : {
338 0 : const GlyphFace *aGlyph = seg->getFace()->getGlyphFaceCache()->glyphSafe(m_realglyphid);
339 0 : if (aGlyph) theGlyph = aGlyph;
340 : }
341 0 : m_advance = Position(theGlyph->theAdvance().x, 0.);
342 : }
343 :
344 0 : void Slot::floodShift(Position adj)
345 : {
346 0 : m_position += adj;
347 0 : if (m_child) m_child->floodShift(adj);
348 0 : if (m_sibling) m_sibling->floodShift(adj);
349 0 : }
|