Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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/UtfCodec.h"
28 #include <cstring>
29 #include <cstdlib>
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/Bidi.h"
40 #include "graphite2/Segment.h"
43 using namespace graphite2;
45 Segment::Segment(unsigned int numchars, const Face* face, uint32 script, int textDir)
46 : m_freeSlots(NULL),
47 m_freeJustifies(NULL),
48 m_charinfo(new CharInfo[numchars]),
49 m_face(face),
50 m_silf(face->chooseSilf(script)),
51 m_first(NULL),
52 m_last(NULL),
53 m_bufSize(numchars + 10),
54 m_numGlyphs(numchars),
55 m_numCharinfo(numchars),
56 m_passBits(m_silf->aPassBits() ? -1 : 0),
57 m_defaultOriginal(0),
58 m_dir(textDir)
59 {
60 freeSlot(newSlot());
61 m_bufSize = log_binary(numchars)+1;
62 }
64 Segment::~Segment()
65 {
66 for (SlotRope::iterator i = m_slots.begin(); i != m_slots.end(); ++i)
67 free(*i);
68 for (AttributeRope::iterator j = m_userAttrs.begin(); j != m_userAttrs.end(); ++j)
69 free(*j);
70 delete[] m_charinfo;
71 }
73 #ifndef GRAPHITE2_NSEGCACHE
74 SegmentScopeState Segment::setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength)
75 {
76 SegmentScopeState state;
77 state.numGlyphsOutsideScope = m_numGlyphs - subLength;
78 state.realFirstSlot = m_first;
79 state.slotBeforeScope = firstSlot->prev();
80 state.slotAfterScope = lastSlot->next();
81 state.realLastSlot = m_last;
82 firstSlot->prev(NULL);
83 lastSlot->next(NULL);
84 assert(m_defaultOriginal == 0);
85 m_defaultOriginal = firstSlot->original();
86 m_numGlyphs = subLength;
87 m_first = firstSlot;
88 m_last = lastSlot;
89 return state;
90 }
92 void Segment::removeScope(SegmentScopeState & state)
93 {
94 m_numGlyphs = state.numGlyphsOutsideScope + m_numGlyphs;
95 if (state.slotBeforeScope)
96 {
97 state.slotBeforeScope->next(m_first);
98 m_first->prev(state.slotBeforeScope);
99 m_first = state.realFirstSlot;
100 }
101 if (state.slotAfterScope)
102 {
103 state.slotAfterScope->prev(m_last);
104 m_last->next(state.slotAfterScope);
105 m_last = state.realLastSlot;
106 }
107 m_defaultOriginal = 0;
108 }
110 #if 0
111 void Segment::append(const Segment &other)
112 {
113 Rect bbox = other.m_bbox + m_advance;
115 m_slots.insert(m_slots.end(), other.m_slots.begin(), other.m_slots.end());
116 CharInfo* pNewCharInfo = new CharInfo[m_numCharinfo+other.m_numCharinfo]; //since CharInfo has no constructor, this doesn't do much
117 for (unsigned int i=0 ; i<m_numCharinfo ; ++i)
118 pNewCharInfo[i] = m_charinfo[i];
119 m_last->next(other.m_first);
120 other.m_last->prev(m_last);
121 m_userAttrs.insert(m_userAttrs.end(), other.m_userAttrs.begin(), other.m_userAttrs.end());
123 delete[] m_charinfo;
124 m_charinfo = pNewCharInfo;
125 pNewCharInfo += m_numCharinfo ;
126 for (unsigned int i=0 ; i<m_numCharinfo ; ++i)
127 pNewCharInfo[i] = other.m_charinfo[i];
129 m_numCharinfo += other.m_numCharinfo;
130 m_numGlyphs += other.m_numGlyphs;
131 m_advance = m_advance + other.m_advance;
132 m_bbox = m_bbox.widen(bbox);
133 m_passBits &= other.passBits();
134 }
135 #endif
136 #endif // GRAPHITE2_NSEGCACHE
138 void Segment::appendSlot(int id, int cid, int gid, int iFeats, size_t coffset)
139 {
140 Slot *aSlot = newSlot();
142 if (!aSlot) return;
143 m_charinfo[id].init(cid);
144 m_charinfo[id].feats(iFeats);
145 m_charinfo[id].base(coffset);
146 const GlyphFace * theGlyph = m_face->glyphs().glyphSafe(gid);
147 m_charinfo[id].breakWeight(theGlyph ? theGlyph->attrs()[m_silf->aBreak()] : 0);
149 aSlot->child(NULL);
150 aSlot->setGlyph(this, gid, theGlyph);
151 aSlot->originate(id);
152 aSlot->before(id);
153 aSlot->after(id);
154 if (m_last) m_last->next(aSlot);
155 aSlot->prev(m_last);
156 m_last = aSlot;
157 if (!m_first) m_first = aSlot;
158 if (theGlyph && m_silf->aPassBits())
159 m_passBits &= theGlyph->attrs()[m_silf->aPassBits()]
160 | (m_silf->numPasses() > 16 ? (theGlyph->attrs()[m_silf->aPassBits() + 1] << 16) : 0);
161 }
163 Slot *Segment::newSlot()
164 {
165 if (!m_freeSlots)
166 {
167 int numUser = m_silf->numUser();
168 #if !defined GRAPHITE2_NTRACING
169 if (m_face->logger()) ++numUser;
170 #endif
171 Slot *newSlots = grzeroalloc<Slot>(m_bufSize);
172 int16 *newAttrs = grzeroalloc<int16>(numUser * m_bufSize);
173 if (!newSlots || !newAttrs) return NULL;
174 for (size_t i = 0; i < m_bufSize; i++)
175 {
176 newSlots[i].next(newSlots + i + 1);
177 newSlots[i].userAttrs(newAttrs + i * numUser);
178 newSlots[i].setBidiClass(-1);
179 }
180 newSlots[m_bufSize - 1].next(NULL);
181 newSlots[0].next(NULL);
182 m_slots.push_back(newSlots);
183 m_userAttrs.push_back(newAttrs);
184 m_freeSlots = (m_bufSize > 1)? newSlots + 1 : NULL;
185 return newSlots;
186 }
187 Slot *res = m_freeSlots;
188 m_freeSlots = m_freeSlots->next();
189 res->next(NULL);
190 return res;
191 }
193 void Segment::freeSlot(Slot *aSlot)
194 {
195 if (m_last == aSlot) m_last = aSlot->prev();
196 if (m_first == aSlot) m_first = aSlot->next();
197 if (aSlot->attachedTo())
198 aSlot->attachedTo()->removeChild(aSlot);
199 while (aSlot->firstChild())
200 {
201 aSlot->firstChild()->attachTo(NULL);
202 aSlot->removeChild(aSlot->firstChild());
203 }
204 // reset the slot incase it is reused
205 ::new (aSlot) Slot;
206 memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16));
207 // Update generation counter for debug
208 #if !defined GRAPHITE2_NTRACING
209 if (m_face->logger())
210 ++aSlot->userAttrs()[m_silf->numUser()];
211 #endif
212 // update next pointer
213 if (!m_freeSlots)
214 aSlot->next(NULL);
215 else
216 aSlot->next(m_freeSlots);
217 m_freeSlots = aSlot;
218 }
220 SlotJustify *Segment::newJustify()
221 {
222 if (!m_freeJustifies)
223 {
224 const size_t justSize = SlotJustify::size_of(m_silf->numJustLevels());
225 byte *justs = grzeroalloc<byte>(justSize * m_bufSize);
226 if (!justs) return NULL;
227 for (int i = m_bufSize - 2; i >= 0; --i)
228 {
229 SlotJustify *p = reinterpret_cast<SlotJustify *>(justs + justSize * i);
230 SlotJustify *next = reinterpret_cast<SlotJustify *>(justs + justSize * (i + 1));
231 p->next = next;
232 }
233 m_freeJustifies = (SlotJustify *)justs;
234 m_justifies.push_back(m_freeJustifies);
235 }
236 SlotJustify *res = m_freeJustifies;
237 m_freeJustifies = m_freeJustifies->next;
238 res->next = NULL;
239 return res;
240 }
242 void Segment::freeJustify(SlotJustify *aJustify)
243 {
244 int numJust = m_silf->numJustLevels();
245 if (m_silf->numJustLevels() <= 0) numJust = 1;
246 aJustify->next = m_freeJustifies;
247 memset(aJustify->values, 0, numJust*SlotJustify::NUMJUSTPARAMS*sizeof(int16));
248 m_freeJustifies = aJustify;
249 }
251 #ifndef GRAPHITE2_NSEGCACHE
252 void Segment::splice(size_t offset, size_t length, Slot * const startSlot,
253 Slot * endSlot, const Slot * srcSlot,
254 const size_t numGlyphs)
255 {
256 size_t numChars = length;
257 extendLength(numGlyphs - length);
258 // remove any extra
259 if (numGlyphs < length)
260 {
261 Slot * end = endSlot->next();
262 do
263 {
264 endSlot = endSlot->prev();
265 freeSlot(endSlot->next());
266 } while (numGlyphs < --length);
267 endSlot->next(end);
268 if (end)
269 end->prev(endSlot);
270 }
271 else
272 {
273 // insert extra slots if needed
274 while (numGlyphs > length)
275 {
276 Slot * extra = newSlot();
277 if (!extra) return;
278 extra->prev(endSlot);
279 extra->next(endSlot->next());
280 endSlot->next(extra);
281 if (extra->next())
282 extra->next()->prev(extra);
283 if (m_last == endSlot)
284 m_last = extra;
285 endSlot = extra;
286 ++length;
287 }
288 }
290 endSlot = endSlot->next();
291 assert(numGlyphs == length);
292 assert(offset + numChars <= m_numCharinfo);
293 Slot * indexmap[eMaxSpliceSize*3];
294 assert(numGlyphs < sizeof indexmap/sizeof *indexmap);
295 Slot * slot = startSlot;
296 for (uint16 i=0; i < numGlyphs; slot = slot->next(), ++i)
297 indexmap[i] = slot;
299 for (slot = startSlot; slot != endSlot; slot = slot->next(), srcSlot = srcSlot->next())
300 {
301 slot->set(*srcSlot, offset, m_silf->numUser(), m_silf->numJustLevels(), numChars);
302 if (srcSlot->attachedTo()) slot->attachTo(indexmap[srcSlot->attachedTo()->index()]);
303 if (srcSlot->nextSibling()) slot->m_sibling = indexmap[srcSlot->nextSibling()->index()];
304 if (srcSlot->firstChild()) slot->m_child = indexmap[srcSlot->firstChild()->index()];
305 }
306 }
307 #endif // GRAPHITE2_NSEGCACHE
309 void Segment::linkClusters(Slot *s, Slot * end)
310 {
311 end = end->next();
313 for (; s != end && !s->isBase(); s = s->next());
314 Slot * ls = s;
316 if (m_dir & 1)
317 {
318 for (; s != end; s = s->next())
319 {
320 if (!s->isBase()) continue;
322 s->sibling(ls);
323 ls = s;
324 }
325 }
326 else
327 {
328 for (; s != end; s = s->next())
329 {
330 if (!s->isBase()) continue;
332 ls->sibling(s);
333 ls = s;
334 }
335 }
336 }
338 Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd)
339 {
340 Position currpos(0., 0.);
341 float clusterMin = 0.;
342 Rect bbox;
344 if (!iStart) iStart = m_first;
345 if (!iEnd) iEnd = m_last;
347 if (m_dir & 1)
348 {
349 for (Slot * s = iEnd, * const end = iStart->prev(); s && s != end; s = s->prev())
350 {
351 if (s->isBase())
352 currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x);
353 }
354 }
355 else
356 {
357 for (Slot * s = iStart, * const end = iEnd->next(); s && s != end; s = s->next())
358 {
359 if (s->isBase())
360 currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x);
361 }
362 }
363 return currpos;
364 }
367 void Segment::associateChars(int offset, int numChars)
368 {
369 int i = 0, j = 0;
370 CharInfo *c, *cend;
371 for (c = m_charinfo + offset, cend = m_charinfo + offset + numChars; c != cend; ++c)
372 {
373 c->before(-1);
374 c->after(-1);
375 }
376 for (Slot * s = m_first; s; s->index(i++), s = s->next())
377 {
378 j = s->before();
379 if (j < 0) continue;
381 for (const int after = s->after(); j <= after; ++j)
382 {
383 c = charinfo(j);
384 if (c->before() == -1 || i < c->before()) c->before(i);
385 if (c->after() < i) c->after(i);
386 }
387 }
388 for (Slot *s = m_first; s; s = s->next())
389 {
390 int a;
391 for (a = s->after() + 1; a < offset + numChars && charinfo(a)->after() < 0; ++a)
392 { charinfo(a)->after(s->index()); }
393 --a;
394 s->after(a);
396 for (a = s->before() - 1; a >= offset && charinfo(a)->before() < 0; --a)
397 { charinfo(a)->before(s->index()); }
398 ++a;
399 s->before(a);
400 }
401 }
404 template <typename utf_iter>
405 inline void process_utf_data(Segment & seg, const Face & face, const int fid, utf_iter c, size_t n_chars)
406 {
407 const Cmap & cmap = face.cmap();
408 int slotid = 0;
410 const typename utf_iter::codeunit_type * const base = c;
411 for (; n_chars; --n_chars, ++c, ++slotid)
412 {
413 const uint32 usv = *c;
414 uint16 gid = cmap[usv];
415 if (!gid) gid = face.findPseudo(usv);
416 seg.appendSlot(slotid, usv, gid, fid, c - base);
417 }
418 }
421 bool Segment::read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void* pStart, size_t nChars)
422 {
423 assert(face);
424 assert(pFeats);
425 if (!m_charinfo) return false;
427 // utf iterator is self recovering so we don't care about the error state of the iterator.
428 switch (enc)
429 {
430 case gr_utf8: process_utf_data(*this, *face, addFeatures(*pFeats), utf8::const_iterator(pStart), nChars); break;
431 case gr_utf16: process_utf_data(*this, *face, addFeatures(*pFeats), utf16::const_iterator(pStart), nChars); break;
432 case gr_utf32: process_utf_data(*this, *face, addFeatures(*pFeats), utf32::const_iterator(pStart), nChars); break;
433 }
434 return true;
435 }
437 void Segment::prepare_pos(const Font * /*font*/)
438 {
439 // copy key changeable metrics into slot (if any);
440 }
442 Slot *process_bidi(Slot *start, int level, int prelevel, int &nextLevel, int dirover, int isol, int &cisol, int &isolerr, int &embederr, int init, Segment *seg, uint8 aMirror, BracketPairStack &stack);
443 void resolveImplicit(Slot *s, Segment *seg, uint8 aMirror);
444 void resolveWhitespace(int baseLevel, Slot *s);
445 Slot *resolveOrder(Slot * & s, const bool reordered, const int level = 0);
447 void Segment::bidiPass(uint8 aBidi, int paradir, uint8 aMirror)
448 {
449 if (slotCount() == 0)
450 return;
452 Slot *s;
453 int baseLevel = paradir ? 1 : 0;
454 unsigned int bmask = 0;
455 unsigned int ssize = 0;
456 for (s = first(); s; s = s->next())
457 {
458 if (s->getBidiClass() == -1)
459 {
460 unsigned int bAttr = glyphAttr(s->gid(), aBidi);
461 s->setBidiClass((bAttr <= 22) * bAttr);
462 }
463 bmask |= (1 << s->getBidiClass());
464 s->setBidiLevel(baseLevel);
465 if (glyphAttr(s->gid(), aMirror) && s->getBidiClass() == 21)
466 ++ssize;
467 }
469 BracketPairStack bstack(ssize);
470 if (bmask & (paradir ? 0x2E7892 : 0x2E789C))
471 {
472 // O(8N) algorithm, with no working data beyond what is needed for processParens
473 int nextLevel = paradir;
474 int e, i, c;
475 process_bidi(first(), baseLevel, paradir, nextLevel, 0, 0, c = 0, i = 0, e = 0, 1, this, aMirror, bstack);
476 resolveImplicit(first(), this, aMirror);
477 resolveWhitespace(baseLevel, last());
478 s = resolveOrder(s = first(), baseLevel != 0);
479 if (s)
480 {
481 first(s); last(s->prev());
482 s->prev()->next(0); s->prev(0);
483 }
484 }
485 else if (!(dir() & 4) && baseLevel && aMirror)
486 {
487 for (s = first(); s; s = s->next())
488 {
489 unsigned short g = glyphAttr(s->gid(), aMirror);
490 if (g) s->setGlyph(this, g);
491 }
492 }
493 }