Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
1 /* GRAPHITE2 LICENSING
3 Copyright 2010, SIL International
4 All rights reserved.
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.
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.
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.
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/Silf.h"
30 #include "inc/CharInfo.h"
31 #include "inc/Rule.h"
34 using namespace graphite2;
36 Slot::Slot() :
37 m_next(NULL), m_prev(NULL),
38 m_glyphid(0), m_realglyphid(0), m_original(0), m_before(0), m_after(0),
39 m_index(0), m_parent(NULL), m_child(NULL), m_sibling(NULL),
40 m_position(0, 0), m_shift(0, 0), m_advance(0, 0),
41 m_attach(0, 0), m_with(0, 0), m_just(0.),
42 m_flags(0), m_attLevel(0), m_bidiCls(-1), m_bidiLevel(0), m_justs(NULL)
43 // Do not set m_userAttr since it is set *before* new is called since this
44 // is used as a positional new to reset the GrSlot
45 {
46 }
48 // take care, this does not copy any of the GrSlot pointer fields
49 void Slot::set(const Slot & orig, int charOffset, size_t numUserAttr, size_t justLevels, size_t numChars)
50 {
51 // leave m_next and m_prev unchanged
52 m_glyphid = orig.m_glyphid;
53 m_realglyphid = orig.m_realglyphid;
54 m_original = orig.m_original + charOffset;
55 if (charOffset + int(orig.m_before) < 0)
56 m_before = 0;
57 else
58 m_before = orig.m_before + charOffset;
59 if (charOffset <= 0 && orig.m_after + charOffset >= numChars)
60 m_after = numChars - 1;
61 else
62 m_after = orig.m_after + charOffset;
63 m_parent = NULL;
64 m_child = NULL;
65 m_sibling = NULL;
66 m_position = orig.m_position;
67 m_shift = orig.m_shift;
68 m_advance = orig.m_advance;
69 m_attach = orig.m_attach;
70 m_with = orig.m_with;
71 m_flags = orig.m_flags;
72 m_attLevel = orig.m_attLevel;
73 m_bidiCls = orig.m_bidiCls;
74 m_bidiLevel = orig.m_bidiLevel;
75 if (m_userAttr && orig.m_userAttr)
76 memcpy(m_userAttr, orig.m_userAttr, numUserAttr * sizeof(*m_userAttr));
77 if (m_justs && orig.m_justs)
78 memcpy(m_justs, orig.m_justs, SlotJustify::size_of(justLevels));
79 }
81 void Slot::update(int /*numGrSlots*/, int numCharInfo, Position &relpos)
82 {
83 m_before += numCharInfo;
84 m_after += numCharInfo;
85 m_position = m_position + relpos;
86 }
88 Position Slot::finalise(const Segment *seg, const Font *font, Position & base, Rect & bbox, uint8 attrLevel, float & clusterMin)
89 {
90 if (attrLevel && m_attLevel > attrLevel) return Position(0, 0);
91 float scale = 1.0;
92 Position shift(m_shift.x * ((seg->dir() & 1) * -2 + 1) + m_just, m_shift.y);
93 float tAdvance = m_advance.x + m_just;
94 const GlyphFace * glyphFace = seg->getFace()->glyphs().glyphSafe(glyph());
95 if (font)
96 {
97 scale = font->scale();
98 shift *= scale;
99 if (font->isHinted() && glyphFace)
100 tAdvance = (m_advance.x - glyphFace->theAdvance().x + m_just) * scale + font->advance(m_glyphid);
101 else
102 tAdvance *= scale;
103 }
104 Position res;
106 m_position = base + shift;
107 if (!m_parent)
108 {
109 res = base + Position(tAdvance, m_advance.y * scale);
110 clusterMin = base.x;
111 }
112 else
113 {
114 float tAdv;
115 m_position += (m_attach - m_with) * scale;
116 tAdv = m_advance.x >= 0.5 ? m_position.x + tAdvance - shift.x : 0.f;
117 res = Position(tAdv, 0);
118 if ((m_advance.x >= 0.5 || m_position.x < 0) && m_position.x < clusterMin) clusterMin = m_position.x;
119 }
121 if (glyphFace)
122 {
123 Rect ourBbox = glyphFace->theBBox() * scale + m_position;
124 bbox = bbox.widen(ourBbox);
125 }
127 if (m_child && m_child != this && m_child->attachedTo() == this)
128 {
129 Position tRes = m_child->finalise(seg, font, m_position, bbox, attrLevel, clusterMin);
130 if ((!m_parent || m_advance.x >= 0.5) && tRes.x > res.x) res = tRes;
131 }
133 if (m_parent && m_sibling && m_sibling != this && m_sibling->attachedTo() == m_parent)
134 {
135 Position tRes = m_sibling->finalise(seg, font, base, bbox, attrLevel, clusterMin);
136 if (tRes.x > res.x) res = tRes;
137 }
139 if (!m_parent && clusterMin < base.x)
140 {
141 Position adj = Position(base.x - clusterMin, 0.);
142 res += adj;
143 m_position += adj;
144 if (m_child) m_child->floodShift(adj);
145 }
146 return res;
147 }
149 int32 Slot::clusterMetric(const Segment *seg, uint8 metric, uint8 attrLevel)
150 {
151 Position base;
152 Rect bbox = seg->theGlyphBBoxTemporary(glyph());
153 float clusterMin = 0.;
154 Position res = finalise(seg, NULL, base, bbox, attrLevel, clusterMin);
156 switch (metrics(metric))
157 {
158 case kgmetLsb :
159 return static_cast<uint32>(bbox.bl.x);
160 case kgmetRsb :
161 return static_cast<uint32>(res.x - bbox.tr.x);
162 case kgmetBbTop :
163 return static_cast<uint32>(bbox.tr.y);
164 case kgmetBbBottom :
165 return static_cast<uint32>(bbox.bl.y);
166 case kgmetBbLeft :
167 return static_cast<uint32>(bbox.bl.x);
168 case kgmetBbRight :
169 return static_cast<uint32>(bbox.tr.x);
170 case kgmetBbWidth :
171 return static_cast<uint32>(bbox.tr.x - bbox.bl.x);
172 case kgmetBbHeight :
173 return static_cast<uint32>(bbox.tr.y - bbox.bl.y);
174 case kgmetAdvWidth :
175 return static_cast<uint32>(res.x);
176 case kgmetAdvHeight :
177 return static_cast<uint32>(res.y);
178 default :
179 return 0;
180 }
181 }
183 int Slot::getAttr(const Segment *seg, attrCode ind, uint8 subindex) const
184 {
185 if (!this) return 0;
186 if (ind == gr_slatUserDefnV1)
187 {
188 ind = gr_slatUserDefn;
189 subindex = 0;
190 }
191 else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
192 {
193 int indx = ind - gr_slatJStretch;
194 return getJustify(seg, indx / 5, indx % 5);
195 }
197 switch (ind)
198 {
199 case gr_slatAdvX : return int(m_advance.x);
200 case gr_slatAdvY : return int(m_advance.y);
201 case gr_slatAttTo : return m_parent ? 1 : 0;
202 case gr_slatAttX : return int(m_attach.x);
203 case gr_slatAttY : return int(m_attach.y);
204 case gr_slatAttXOff :
205 case gr_slatAttYOff : return 0;
206 case gr_slatAttWithX : return int(m_with.x);
207 case gr_slatAttWithY : return int(m_with.y);
208 case gr_slatAttWithXOff:
209 case gr_slatAttWithYOff:return 0;
210 case gr_slatAttLevel : return m_attLevel;
211 case gr_slatBreak : return seg->charinfo(m_original)->breakWeight();
212 case gr_slatCompRef : return 0;
213 case gr_slatDir : if (m_bidiCls == -1)
214 const_cast<Slot *>(this)->setBidiClass(seg->glyphAttr(gid(), seg->silf()->aBidi()));
215 return m_bidiCls;
216 case gr_slatInsert : return isInsertBefore();
217 case gr_slatPosX : return int(m_position.x); // but need to calculate it
218 case gr_slatPosY : return int(m_position.y);
219 case gr_slatShiftX : return int(m_shift.x);
220 case gr_slatShiftY : return int(m_shift.y);
221 case gr_slatMeasureSol: return -1; // err what's this?
222 case gr_slatMeasureEol: return -1;
223 case gr_slatJWidth: return int(m_just);
224 case gr_slatUserDefn : return m_userAttr[subindex];
225 case gr_slatSegSplit : return seg->charinfo(m_original)->flags() & 3;
226 case gr_slatBidiLevel: return m_bidiLevel;
227 default : return 0;
228 }
229 }
231 void Slot::setAttr(Segment *seg, attrCode ind, uint8 subindex, int16 value, const SlotMap & map)
232 {
233 if (!this) return;
234 if (ind == gr_slatUserDefnV1)
235 {
236 ind = gr_slatUserDefn;
237 subindex = 0;
238 }
239 else if (ind >= gr_slatJStretch && ind < gr_slatJStretch + 20 && ind != gr_slatJWidth)
240 {
241 int indx = ind - gr_slatJStretch;
242 return setJustify(seg, indx / 5, indx % 5, value);
243 }
245 switch (ind)
246 {
247 case gr_slatAdvX : m_advance.x = value; break;
248 case gr_slatAdvY : m_advance.y = value; break;
249 case gr_slatAttTo :
250 {
251 const uint16 idx = uint16(value);
252 if (idx < map.size() && map[idx])
253 {
254 Slot *other = map[idx];
255 if (other == this) break;
256 if (m_parent) m_parent->removeChild(this);
257 if (other->child(this))
258 {
259 attachTo(other);
260 if (((seg->dir() & 1) != 0) ^ (idx > subindex))
261 m_with = Position(advance(), 0);
262 else // normal match to previous root
263 m_attach = Position(other->advance(), 0);
264 }
265 }
266 break;
267 }
268 case gr_slatAttX : m_attach.x = value; break;
269 case gr_slatAttY : m_attach.y = value; break;
270 case gr_slatAttXOff :
271 case gr_slatAttYOff : break;
272 case gr_slatAttWithX : m_with.x = value; break;
273 case gr_slatAttWithY : m_with.y = value; break;
274 case gr_slatAttWithXOff :
275 case gr_slatAttWithYOff : break;
276 case gr_slatAttLevel :
277 m_attLevel = byte(value);
278 break;
279 case gr_slatBreak :
280 seg->charinfo(m_original)->breakWeight(value);
281 break;
282 case gr_slatCompRef : break; // not sure what to do here
283 case gr_slatDir : m_bidiCls = value; break;
284 case gr_slatInsert :
285 markInsertBefore(value? true : false);
286 break;
287 case gr_slatPosX : break; // can't set these here
288 case gr_slatPosY : break;
289 case gr_slatShiftX : m_shift.x = value; break;
290 case gr_slatShiftY : m_shift.y = value; break;
291 case gr_slatMeasureSol : break;
292 case gr_slatMeasureEol : break;
293 case gr_slatJWidth : just(value); break;
294 case gr_slatSegSplit : seg->charinfo(m_original)->addflags(value & 3); break;
295 case gr_slatUserDefn : m_userAttr[subindex] = value; break;
296 default :
297 break;
298 }
299 }
301 int Slot::getJustify(const Segment *seg, uint8 level, uint8 subindex) const
302 {
303 if (level && level >= seg->silf()->numJustLevels()) return 0;
305 if (m_justs)
306 return m_justs->values[level * SlotJustify::NUMJUSTPARAMS + subindex];
308 if (level >= seg->silf()->numJustLevels()) return 0;
309 Justinfo *jAttrs = seg->silf()->justAttrs() + level;
311 switch (subindex) {
312 case 0 : return seg->glyphAttr(gid(), jAttrs->attrStretch());
313 case 1 : return seg->glyphAttr(gid(), jAttrs->attrShrink());
314 case 2 : return seg->glyphAttr(gid(), jAttrs->attrStep());
315 case 3 : return seg->glyphAttr(gid(), jAttrs->attrWeight());
316 case 4 : return 0; // not been set yet, so clearly 0
317 default: return 0;
318 }
319 }
321 void Slot::setJustify(Segment *seg, uint8 level, uint8 subindex, int16 value)
322 {
323 if (level && level >= seg->silf()->numJustLevels()) return;
324 if (!m_justs)
325 {
326 SlotJustify *j = seg->newJustify();
327 if (!j) return;
328 j->LoadSlot(this, seg);
329 m_justs = j;
330 }
331 m_justs->values[level * SlotJustify::NUMJUSTPARAMS + subindex] = value;
332 }
334 bool Slot::child(Slot *ap)
335 {
336 if (this == ap) return false;
337 else if (ap == m_child) return true;
338 else if (!m_child)
339 m_child = ap;
340 else
341 return m_child->sibling(ap);
342 return true;
343 }
345 bool Slot::sibling(Slot *ap)
346 {
347 if (this == ap) return false;
348 else if (ap == m_sibling) return true;
349 else if (!m_sibling || !ap)
350 m_sibling = ap;
351 else
352 return m_sibling->sibling(ap);
353 return true;
354 }
356 bool Slot::removeChild(Slot *ap)
357 {
358 if (this == ap || !m_child) return false;
359 else if (ap == m_child)
360 {
361 Slot *nSibling = m_child->nextSibling();
362 m_child->sibling(NULL);
363 m_child = nSibling;
364 return true;
365 }
366 else
367 return m_child->removeSibling(ap);
368 return true;
369 }
371 bool Slot::removeSibling(Slot *ap)
372 {
373 if (this == ap || !m_sibling) return false;
374 else if (ap == m_sibling)
375 {
376 m_sibling = m_sibling->nextSibling();
377 return true;
378 }
379 else
380 return m_sibling->removeSibling(ap);
381 return true;
382 }
384 void Slot::setGlyph(Segment *seg, uint16 glyphid, const GlyphFace * theGlyph)
385 {
386 m_glyphid = glyphid;
387 if (!theGlyph)
388 {
389 theGlyph = seg->getFace()->glyphs().glyphSafe(glyphid);
390 if (!theGlyph)
391 {
392 m_realglyphid = 0;
393 m_advance = Position(0.,0.);
394 return;
395 }
396 }
397 m_realglyphid = theGlyph->attrs()[seg->silf()->aPseudo()];
398 const GlyphFace *aGlyph = theGlyph;
399 if (m_realglyphid)
400 {
401 aGlyph = seg->getFace()->glyphs().glyphSafe(m_realglyphid);
402 if (!aGlyph) aGlyph = theGlyph;
403 }
404 m_advance = Position(aGlyph->theAdvance().x, 0.);
405 if (seg->silf()->aPassBits())
406 seg->mergePassBits(theGlyph->attrs()[seg->silf()->aPassBits()]);
407 }
409 void Slot::floodShift(Position adj)
410 {
411 m_position += adj;
412 if (m_child) m_child->floodShift(adj);
413 if (m_sibling) m_sibling->floodShift(adj);
414 }
416 void SlotJustify::LoadSlot(const Slot *s, const Segment *seg)
417 {
418 for (int i = seg->silf()->numJustLevels() - 1; i >= 0; --i)
419 {
420 Justinfo *justs = seg->silf()->justAttrs() + i;
421 int16 *v = values + i * NUMJUSTPARAMS;
422 v[0] = seg->glyphAttr(s->gid(), justs->attrStretch());
423 v[1] = seg->glyphAttr(s->gid(), justs->attrShrink());
424 v[2] = seg->glyphAttr(s->gid(), justs->attrStep());
425 v[3] = seg->glyphAttr(s->gid(), justs->attrWeight());
426 }
427 }