Line data Source code
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/UtfCodec.h"
28 : #include <cstring>
29 : #include <cstdlib>
30 :
31 : #include "inc/bits.h"
32 : #include "inc/Segment.h"
33 : #include "graphite2/Font.h"
34 : #include "inc/CharInfo.h"
35 : #include "inc/debug.h"
36 : #include "inc/Slot.h"
37 : #include "inc/Main.h"
38 : #include "inc/CmapCache.h"
39 : #include "inc/Collider.h"
40 : #include "graphite2/Segment.h"
41 :
42 :
43 : using namespace graphite2;
44 :
45 0 : Segment::Segment(unsigned int numchars, const Face* face, uint32 script, int textDir)
46 : : m_freeSlots(NULL),
47 : m_freeJustifies(NULL),
48 0 : m_charinfo(new CharInfo[numchars]),
49 : m_collisions(NULL),
50 : m_face(face),
51 0 : m_silf(face->chooseSilf(script)),
52 : m_first(NULL),
53 : m_last(NULL),
54 0 : m_bufSize(numchars + 10),
55 : m_numGlyphs(numchars),
56 : m_numCharinfo(numchars),
57 0 : m_passBits(m_silf->aPassBits() ? -1 : 0),
58 : m_defaultOriginal(0),
59 : m_dir(textDir),
60 0 : m_flags(((m_silf->flags() & 0x20) != 0) << 1)
61 : {
62 0 : freeSlot(newSlot());
63 0 : m_bufSize = log_binary(numchars)+1;
64 0 : }
65 :
66 0 : Segment::~Segment()
67 : {
68 0 : for (SlotRope::iterator i = m_slots.begin(); i != m_slots.end(); ++i)
69 0 : free(*i);
70 0 : for (AttributeRope::iterator i = m_userAttrs.begin(); i != m_userAttrs.end(); ++i)
71 0 : free(*i);
72 0 : for (JustifyRope::iterator i = m_justifies.begin(); i != m_justifies.end(); ++i)
73 0 : free(*i);
74 0 : delete[] m_charinfo;
75 0 : free(m_collisions);
76 0 : }
77 :
78 : #ifndef GRAPHITE2_NSEGCACHE
79 : SegmentScopeState Segment::setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength)
80 : {
81 : SegmentScopeState state;
82 : state.numGlyphsOutsideScope = m_numGlyphs - subLength;
83 : state.realFirstSlot = m_first;
84 : state.slotBeforeScope = firstSlot->prev();
85 : state.slotAfterScope = lastSlot->next();
86 : state.realLastSlot = m_last;
87 : firstSlot->prev(NULL);
88 : lastSlot->next(NULL);
89 : assert(m_defaultOriginal == 0);
90 : m_defaultOriginal = firstSlot->original();
91 : m_numGlyphs = subLength;
92 : m_first = firstSlot;
93 : m_last = lastSlot;
94 : return state;
95 : }
96 :
97 : void Segment::removeScope(SegmentScopeState & state)
98 : {
99 : m_numGlyphs = state.numGlyphsOutsideScope + m_numGlyphs;
100 : if (state.slotBeforeScope)
101 : {
102 : state.slotBeforeScope->next(m_first);
103 : m_first->prev(state.slotBeforeScope);
104 : m_first = state.realFirstSlot;
105 : }
106 : if (state.slotAfterScope)
107 : {
108 : state.slotAfterScope->prev(m_last);
109 : m_last->next(state.slotAfterScope);
110 : m_last = state.realLastSlot;
111 : }
112 : m_defaultOriginal = 0;
113 : }
114 :
115 : #if 0
116 : void Segment::append(const Segment &other)
117 : {
118 : Rect bbox = other.m_bbox + m_advance;
119 :
120 : m_slots.insert(m_slots.end(), other.m_slots.begin(), other.m_slots.end());
121 : CharInfo* pNewCharInfo = new CharInfo[m_numCharinfo+other.m_numCharinfo]; //since CharInfo has no constructor, this doesn't do much
122 : for (unsigned int i=0 ; i<m_numCharinfo ; ++i)
123 : pNewCharInfo[i] = m_charinfo[i];
124 : m_last->next(other.m_first);
125 : other.m_last->prev(m_last);
126 : m_userAttrs.insert(m_userAttrs.end(), other.m_userAttrs.begin(), other.m_userAttrs.end());
127 :
128 : delete[] m_charinfo;
129 : m_charinfo = pNewCharInfo;
130 : pNewCharInfo += m_numCharinfo ;
131 : for (unsigned int i=0 ; i<m_numCharinfo ; ++i)
132 : pNewCharInfo[i] = other.m_charinfo[i];
133 :
134 : m_numCharinfo += other.m_numCharinfo;
135 : m_numGlyphs += other.m_numGlyphs;
136 : m_advance = m_advance + other.m_advance;
137 : m_bbox = m_bbox.widen(bbox);
138 : m_passBits &= other.passBits();
139 : }
140 : #endif
141 : #endif // GRAPHITE2_NSEGCACHE
142 :
143 0 : void Segment::appendSlot(int id, int cid, int gid, int iFeats, size_t coffset)
144 : {
145 0 : Slot *aSlot = newSlot();
146 :
147 0 : if (!aSlot) return;
148 0 : m_charinfo[id].init(cid);
149 0 : m_charinfo[id].feats(iFeats);
150 0 : m_charinfo[id].base(coffset);
151 0 : const GlyphFace * theGlyph = m_face->glyphs().glyphSafe(gid);
152 0 : m_charinfo[id].breakWeight(theGlyph ? theGlyph->attrs()[m_silf->aBreak()] : 0);
153 :
154 0 : aSlot->child(NULL);
155 0 : aSlot->setGlyph(this, gid, theGlyph);
156 0 : aSlot->originate(id);
157 0 : aSlot->before(id);
158 0 : aSlot->after(id);
159 0 : if (m_last) m_last->next(aSlot);
160 0 : aSlot->prev(m_last);
161 0 : m_last = aSlot;
162 0 : if (!m_first) m_first = aSlot;
163 0 : if (theGlyph && m_silf->aPassBits())
164 0 : m_passBits &= theGlyph->attrs()[m_silf->aPassBits()]
165 0 : | (m_silf->numPasses() > 16 ? (theGlyph->attrs()[m_silf->aPassBits() + 1] << 16) : 0);
166 : }
167 :
168 0 : Slot *Segment::newSlot()
169 : {
170 0 : if (!m_freeSlots)
171 : {
172 : // check that the segment doesn't grow indefinintely
173 0 : if (m_numGlyphs > m_numCharinfo * MAX_SEG_GROWTH_FACTOR)
174 0 : return NULL;
175 0 : int numUser = m_silf->numUser();
176 : #if !defined GRAPHITE2_NTRACING
177 : if (m_face->logger()) ++numUser;
178 : #endif
179 0 : Slot *newSlots = grzeroalloc<Slot>(m_bufSize);
180 0 : int16 *newAttrs = grzeroalloc<int16>(m_bufSize * numUser);
181 0 : if (!newSlots || !newAttrs)
182 : {
183 0 : free(newSlots);
184 0 : free(newAttrs);
185 0 : return NULL;
186 : }
187 0 : for (size_t i = 0; i < m_bufSize; i++)
188 : {
189 0 : ::new (newSlots + i) Slot(newAttrs + i * numUser);
190 0 : newSlots[i].next(newSlots + i + 1);
191 : }
192 0 : newSlots[m_bufSize - 1].next(NULL);
193 0 : newSlots[0].next(NULL);
194 0 : m_slots.push_back(newSlots);
195 0 : m_userAttrs.push_back(newAttrs);
196 0 : m_freeSlots = (m_bufSize > 1)? newSlots + 1 : NULL;
197 0 : return newSlots;
198 : }
199 0 : Slot *res = m_freeSlots;
200 0 : m_freeSlots = m_freeSlots->next();
201 0 : res->next(NULL);
202 0 : return res;
203 : }
204 :
205 0 : void Segment::freeSlot(Slot *aSlot)
206 : {
207 0 : if (m_last == aSlot) m_last = aSlot->prev();
208 0 : if (m_first == aSlot) m_first = aSlot->next();
209 0 : if (aSlot->attachedTo())
210 0 : aSlot->attachedTo()->removeChild(aSlot);
211 0 : while (aSlot->firstChild())
212 : {
213 0 : if (aSlot->firstChild()->attachedTo() == aSlot)
214 : {
215 0 : aSlot->firstChild()->attachTo(NULL);
216 0 : aSlot->removeChild(aSlot->firstChild());
217 : }
218 : else
219 0 : aSlot->firstChild(NULL);
220 : }
221 : // reset the slot incase it is reused
222 0 : ::new (aSlot) Slot(aSlot->userAttrs());
223 0 : memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16));
224 : // Update generation counter for debug
225 : #if !defined GRAPHITE2_NTRACING
226 : if (m_face->logger())
227 : ++aSlot->userAttrs()[m_silf->numUser()];
228 : #endif
229 : // update next pointer
230 0 : if (!m_freeSlots)
231 0 : aSlot->next(NULL);
232 : else
233 0 : aSlot->next(m_freeSlots);
234 0 : m_freeSlots = aSlot;
235 0 : }
236 :
237 0 : SlotJustify *Segment::newJustify()
238 : {
239 0 : if (!m_freeJustifies)
240 : {
241 0 : const size_t justSize = SlotJustify::size_of(m_silf->numJustLevels());
242 0 : byte *justs = grzeroalloc<byte>(justSize * m_bufSize);
243 0 : if (!justs) return NULL;
244 0 : for (int i = m_bufSize - 2; i >= 0; --i)
245 : {
246 0 : SlotJustify *p = reinterpret_cast<SlotJustify *>(justs + justSize * i);
247 0 : SlotJustify *next = reinterpret_cast<SlotJustify *>(justs + justSize * (i + 1));
248 0 : p->next = next;
249 : }
250 0 : m_freeJustifies = (SlotJustify *)justs;
251 0 : m_justifies.push_back(m_freeJustifies);
252 : }
253 0 : SlotJustify *res = m_freeJustifies;
254 0 : m_freeJustifies = m_freeJustifies->next;
255 0 : res->next = NULL;
256 0 : return res;
257 : }
258 :
259 0 : void Segment::freeJustify(SlotJustify *aJustify)
260 : {
261 0 : int numJust = m_silf->numJustLevels();
262 0 : if (m_silf->numJustLevels() <= 0) numJust = 1;
263 0 : aJustify->next = m_freeJustifies;
264 0 : memset(aJustify->values, 0, numJust*SlotJustify::NUMJUSTPARAMS*sizeof(int16));
265 0 : m_freeJustifies = aJustify;
266 0 : }
267 :
268 : #ifndef GRAPHITE2_NSEGCACHE
269 : void Segment::splice(size_t offset, size_t length, Slot * const startSlot,
270 : Slot * endSlot, const Slot * srcSlot,
271 : const size_t numGlyphs)
272 : {
273 : size_t numChars = length;
274 : extendLength(numGlyphs - length);
275 : // remove any extra
276 : if (numGlyphs < length)
277 : {
278 : Slot * end = endSlot->next();
279 : do
280 : {
281 : endSlot = endSlot->prev();
282 : freeSlot(endSlot->next());
283 : } while (numGlyphs < --length);
284 : endSlot->next(end);
285 : if (end)
286 : end->prev(endSlot);
287 : }
288 : else
289 : {
290 : // insert extra slots if needed
291 : while (numGlyphs > length)
292 : {
293 : Slot * extra = newSlot();
294 : if (!extra) return;
295 : extra->prev(endSlot);
296 : extra->next(endSlot->next());
297 : endSlot->next(extra);
298 : if (extra->next())
299 : extra->next()->prev(extra);
300 : if (m_last == endSlot)
301 : m_last = extra;
302 : endSlot = extra;
303 : ++length;
304 : }
305 : }
306 :
307 : endSlot = endSlot->next();
308 : assert(numGlyphs == length);
309 : assert(offset + numChars <= m_numCharinfo);
310 : Slot * indexmap[eMaxSpliceSize*3];
311 : assert(numGlyphs < sizeof indexmap/sizeof *indexmap);
312 : Slot * slot = startSlot;
313 : for (uint16 i=0; i < numGlyphs; slot = slot->next(), ++i)
314 : indexmap[i] = slot;
315 :
316 : for (slot = startSlot; slot != endSlot; slot = slot->next(), srcSlot = srcSlot->next())
317 : {
318 : slot->set(*srcSlot, offset, m_silf->numUser(), m_silf->numJustLevels(), numChars);
319 : if (srcSlot->attachedTo()) slot->attachTo(indexmap[srcSlot->attachedTo()->index()]);
320 : if (srcSlot->nextSibling()) slot->m_sibling = indexmap[srcSlot->nextSibling()->index()];
321 : if (srcSlot->firstChild()) slot->m_child = indexmap[srcSlot->firstChild()->index()];
322 : }
323 : }
324 : #endif // GRAPHITE2_NSEGCACHE
325 :
326 : // reverse the slots but keep diacritics in their same position after their bases
327 0 : void Segment::reverseSlots()
328 : {
329 0 : m_dir = m_dir ^ 64; // invert the reverse flag
330 0 : if (m_first == m_last) return; // skip 0 or 1 glyph runs
331 :
332 0 : Slot *t = 0;
333 0 : Slot *curr = m_first;
334 : Slot *tlast;
335 : Slot *tfirst;
336 0 : Slot *out = 0;
337 :
338 0 : while (curr && getSlotBidiClass(curr) == 16)
339 0 : curr = curr->next();
340 0 : if (!curr) return;
341 0 : tfirst = curr->prev();
342 0 : tlast = curr;
343 :
344 0 : while (curr)
345 : {
346 0 : if (getSlotBidiClass(curr) == 16)
347 : {
348 0 : Slot *d = curr->next();
349 0 : while (d && getSlotBidiClass(d) == 16)
350 0 : d = d->next();
351 :
352 0 : d = d ? d->prev() : m_last;
353 0 : Slot *p = out->next(); // one after the diacritics. out can't be null
354 0 : if (p)
355 0 : p->prev(d);
356 : else
357 0 : tlast = d;
358 0 : t = d->next();
359 0 : d->next(p);
360 0 : curr->prev(out);
361 0 : out->next(curr);
362 : }
363 : else // will always fire first time round the loop
364 : {
365 0 : if (out)
366 0 : out->prev(curr);
367 0 : t = curr->next();
368 0 : curr->next(out);
369 0 : out = curr;
370 : }
371 0 : curr = t;
372 : }
373 0 : out->prev(tfirst);
374 0 : if (tfirst)
375 0 : tfirst->next(out);
376 : else
377 0 : m_first = out;
378 0 : m_last = tlast;
379 : }
380 :
381 0 : void Segment::linkClusters(Slot *s, Slot * end)
382 : {
383 0 : end = end->next();
384 :
385 0 : for (; s != end && !s->isBase(); s = s->next());
386 0 : Slot * ls = s;
387 :
388 0 : if (m_dir & 1)
389 : {
390 0 : for (; s != end; s = s->next())
391 : {
392 0 : if (!s->isBase()) continue;
393 :
394 0 : s->sibling(ls);
395 0 : ls = s;
396 : }
397 : }
398 : else
399 : {
400 0 : for (; s != end; s = s->next())
401 : {
402 0 : if (!s->isBase()) continue;
403 :
404 0 : ls->sibling(s);
405 0 : ls = s;
406 : }
407 : }
408 0 : }
409 :
410 0 : Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bool isRtl, bool isFinal)
411 : {
412 0 : Position currpos(0., 0.);
413 0 : float clusterMin = 0.;
414 0 : Rect bbox;
415 0 : bool reorder = (currdir() != isRtl);
416 :
417 0 : if (reorder)
418 : {
419 : Slot *temp;
420 0 : reverseSlots();
421 0 : temp = iStart;
422 0 : iStart = iEnd;
423 0 : iEnd = temp;
424 : }
425 0 : if (!iStart) iStart = m_first;
426 0 : if (!iEnd) iEnd = m_last;
427 :
428 0 : if (!iStart || !iEnd) // only true for empty segments
429 0 : return currpos;
430 :
431 0 : if (isRtl)
432 : {
433 0 : for (Slot * s = iEnd, * const end = iStart->prev(); s && s != end; s = s->prev())
434 : {
435 0 : if (s->isBase())
436 0 : currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isRtl, isFinal);
437 : }
438 : }
439 : else
440 : {
441 0 : for (Slot * s = iStart, * const end = iEnd->next(); s && s != end; s = s->next())
442 : {
443 0 : if (s->isBase())
444 0 : currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isRtl, isFinal);
445 : }
446 : }
447 0 : if (reorder)
448 0 : reverseSlots();
449 0 : return currpos;
450 : }
451 :
452 :
453 0 : void Segment::associateChars(int offset, int numChars)
454 : {
455 0 : int i = 0, j = 0;
456 : CharInfo *c, *cend;
457 0 : for (c = m_charinfo + offset, cend = m_charinfo + offset + numChars; c != cend; ++c)
458 : {
459 0 : c->before(-1);
460 0 : c->after(-1);
461 : }
462 0 : for (Slot * s = m_first; s; s->index(i++), s = s->next())
463 : {
464 0 : j = s->before();
465 0 : if (j < 0) continue;
466 :
467 0 : for (const int after = s->after(); j <= after; ++j)
468 : {
469 0 : c = charinfo(j);
470 0 : if (c->before() == -1 || i < c->before()) c->before(i);
471 0 : if (c->after() < i) c->after(i);
472 : }
473 : }
474 0 : for (Slot *s = m_first; s; s = s->next())
475 : {
476 : int a;
477 0 : for (a = s->after() + 1; a < offset + numChars && charinfo(a)->after() < 0; ++a)
478 0 : { charinfo(a)->after(s->index()); }
479 0 : --a;
480 0 : s->after(a);
481 :
482 0 : for (a = s->before() - 1; a >= offset && charinfo(a)->before() < 0; --a)
483 0 : { charinfo(a)->before(s->index()); }
484 0 : ++a;
485 0 : s->before(a);
486 : }
487 0 : }
488 :
489 :
490 : template <typename utf_iter>
491 0 : inline void process_utf_data(Segment & seg, const Face & face, const int fid, utf_iter c, size_t n_chars)
492 : {
493 0 : const Cmap & cmap = face.cmap();
494 0 : int slotid = 0;
495 :
496 0 : const typename utf_iter::codeunit_type * const base = c;
497 0 : for (; n_chars; --n_chars, ++c, ++slotid)
498 : {
499 0 : const uint32 usv = *c;
500 0 : uint16 gid = cmap[usv];
501 0 : if (!gid) gid = face.findPseudo(usv);
502 0 : seg.appendSlot(slotid, usv, gid, fid, c - base);
503 : }
504 0 : }
505 :
506 :
507 0 : bool Segment::read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void* pStart, size_t nChars)
508 : {
509 0 : assert(face);
510 0 : assert(pFeats);
511 0 : if (!m_charinfo) return false;
512 :
513 : // utf iterator is self recovering so we don't care about the error state of the iterator.
514 0 : switch (enc)
515 : {
516 0 : case gr_utf8: process_utf_data(*this, *face, addFeatures(*pFeats), utf8::const_iterator(pStart), nChars); break;
517 0 : case gr_utf16: process_utf_data(*this, *face, addFeatures(*pFeats), utf16::const_iterator(pStart), nChars); break;
518 0 : case gr_utf32: process_utf_data(*this, *face, addFeatures(*pFeats), utf32::const_iterator(pStart), nChars); break;
519 : }
520 0 : return true;
521 : }
522 :
523 0 : void Segment::doMirror(uint16 aMirror)
524 : {
525 : Slot * s;
526 0 : for (s = m_first; s; s = s->next())
527 : {
528 0 : unsigned short g = glyphAttr(s->gid(), aMirror);
529 0 : if (g && (!(dir() & 4) || !glyphAttr(s->gid(), aMirror + 1)))
530 0 : s->setGlyph(this, g);
531 : }
532 0 : }
533 :
534 0 : bool Segment::initCollisions()
535 : {
536 0 : m_collisions = grzeroalloc<SlotCollision>(slotCount());
537 0 : if (!m_collisions) return false;
538 :
539 0 : for (Slot *p = m_first; p; p = p->next())
540 0 : if (p->index() < slotCount())
541 0 : ::new (collisionInfo(p)) SlotCollision(this, p);
542 : else
543 0 : return false;
544 0 : return true;
545 : }
|