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/Segment.h"
32 : #include "graphite2/Font.h"
33 : #include "inc/CharInfo.h"
34 : #include "inc/Slot.h"
35 : #include "inc/Main.h"
36 : #include "inc/CmapCache.h"
37 : #include "graphite2/Segment.h"
38 :
39 :
40 : using namespace graphite2;
41 :
42 0 : Segment::Segment(unsigned int numchars, const Face* face, uint32 script, int textDir) :
43 : m_freeSlots(NULL),
44 : m_first(NULL),
45 : m_last(NULL),
46 : m_numGlyphs(numchars),
47 : m_numCharinfo(numchars),
48 : m_defaultOriginal(0),
49 0 : m_charinfo(new CharInfo[numchars]),
50 : m_face(face),
51 0 : m_silf(face->chooseSilf(script)),
52 : m_bbox(Rect(Position(0, 0), Position(0, 0))),
53 0 : m_dir(textDir)
54 : {
55 : unsigned int i, j;
56 0 : m_bufSize = numchars + 10;
57 0 : freeSlot(newSlot());
58 0 : for (i = 0, j = 1; j < numchars; i++, j <<= 1) {}
59 0 : if (!i) i = 1;
60 0 : m_bufSize = i; // log2(numchars)
61 0 : }
62 :
63 0 : Segment::~Segment()
64 : {
65 0 : for (SlotRope::iterator i = m_slots.begin(); i != m_slots.end(); ++i)
66 0 : free(*i);
67 0 : for (AttributeRope::iterator j = m_userAttrs.begin(); j != m_userAttrs.end(); ++j)
68 0 : free(*j);
69 0 : delete[] m_charinfo;
70 0 : }
71 :
72 : #ifndef GRAPHITE2_NSEGCACHE
73 : SegmentScopeState Segment::setScope(Slot * firstSlot, Slot * lastSlot, size_t subLength)
74 : {
75 : SegmentScopeState state;
76 : state.numGlyphsOutsideScope = m_numGlyphs - subLength;
77 : state.realFirstSlot = m_first;
78 : state.slotBeforeScope = firstSlot->prev();
79 : state.slotAfterScope = lastSlot->next();
80 : state.realLastSlot = m_last;
81 : firstSlot->prev(NULL);
82 : lastSlot->next(NULL);
83 : assert(m_defaultOriginal == 0);
84 : m_defaultOriginal = firstSlot->original();
85 : m_numGlyphs = subLength;
86 : m_first = firstSlot;
87 : m_last = lastSlot;
88 : return state;
89 : }
90 :
91 : void Segment::removeScope(SegmentScopeState & state)
92 : {
93 : m_numGlyphs = state.numGlyphsOutsideScope + m_numGlyphs;
94 : if (state.slotBeforeScope)
95 : {
96 : state.slotBeforeScope->next(m_first);
97 : m_first->prev(state.slotBeforeScope);
98 : m_first = state.realFirstSlot;
99 : }
100 : if (state.slotAfterScope)
101 : {
102 : state.slotAfterScope->prev(m_last);
103 : m_last->next(state.slotAfterScope);
104 : m_last = state.realLastSlot;
105 : }
106 : m_defaultOriginal = 0;
107 : }
108 :
109 :
110 : void Segment::append(const Segment &other)
111 : {
112 : Rect bbox = other.m_bbox + m_advance;
113 :
114 : m_slots.insert(m_slots.end(), other.m_slots.begin(), other.m_slots.end());
115 : CharInfo* pNewCharInfo = new CharInfo[m_numCharinfo+other.m_numCharinfo]; //since CharInfo has no constructor, this doesn't do much
116 : for (unsigned int i=0 ; i<m_numCharinfo ; ++i)
117 : pNewCharInfo[i] = m_charinfo[i];
118 : m_last->next(other.m_first);
119 : other.m_last->prev(m_last);
120 : m_userAttrs.insert(m_userAttrs.end(), other.m_userAttrs.begin(), other.m_userAttrs.end());
121 :
122 : delete[] m_charinfo;
123 : m_charinfo = pNewCharInfo;
124 : pNewCharInfo += m_numCharinfo ;
125 : for (unsigned int i=0 ; i<m_numCharinfo ; ++i)
126 : pNewCharInfo[i] = other.m_charinfo[i];
127 :
128 : m_numCharinfo += other.m_numCharinfo;
129 : m_numGlyphs += other.m_numGlyphs;
130 : m_advance = m_advance + other.m_advance;
131 : m_bbox = m_bbox.widen(bbox);
132 : }
133 : #endif // GRAPHITE2_NSEGCACHE
134 :
135 0 : void Segment::appendSlot(int id, int cid, int gid, int iFeats, size_t coffset)
136 : {
137 0 : Slot *aSlot = newSlot();
138 :
139 0 : m_charinfo[id].init(cid);
140 0 : m_charinfo[id].feats(iFeats);
141 0 : m_charinfo[id].base(coffset);
142 0 : const GlyphFace * theGlyph = m_face->getGlyphFaceCache()->glyphSafe(gid);
143 0 : if (theGlyph)
144 : {
145 0 : m_charinfo[id].breakWeight(theGlyph->getAttr(m_silf->aBreak()));
146 : }
147 : else
148 : {
149 0 : m_charinfo[id].breakWeight(0);
150 : }
151 :
152 0 : aSlot->child(NULL);
153 0 : aSlot->setGlyph(this, gid, theGlyph);
154 0 : aSlot->originate(id);
155 0 : aSlot->before(id);
156 0 : aSlot->after(id);
157 0 : if (m_last) m_last->next(aSlot);
158 0 : aSlot->prev(m_last);
159 0 : m_last = aSlot;
160 0 : if (!m_first) m_first = aSlot;
161 0 : }
162 :
163 0 : Slot *Segment::newSlot()
164 : {
165 0 : if (!m_freeSlots)
166 : {
167 0 : int numUser = m_silf->numUser();
168 0 : Slot *newSlots = grzeroalloc<Slot>(m_bufSize);
169 0 : int16 *newAttrs = grzeroalloc<int16>(numUser * m_bufSize);
170 0 : newSlots[0].userAttrs(newAttrs);
171 0 : for (size_t i = 1; i < m_bufSize - 1; i++)
172 : {
173 0 : newSlots[i].next(newSlots + i + 1);
174 0 : newSlots[i].userAttrs(newAttrs + i * numUser);
175 : }
176 0 : newSlots[m_bufSize - 1].userAttrs(newAttrs + (m_bufSize - 1) * numUser);
177 0 : newSlots[m_bufSize - 1].next(NULL);
178 0 : m_slots.push_back(newSlots);
179 0 : m_userAttrs.push_back(newAttrs);
180 0 : m_freeSlots = (m_bufSize > 1)? newSlots + 1 : NULL;
181 0 : return newSlots;
182 : }
183 0 : Slot *res = m_freeSlots;
184 0 : m_freeSlots = m_freeSlots->next();
185 0 : res->next(NULL);
186 0 : return res;
187 : }
188 :
189 0 : void Segment::freeSlot(Slot *aSlot)
190 : {
191 0 : if (m_last == aSlot) m_last = aSlot->prev();
192 0 : if (m_first == aSlot) m_first = aSlot->next();
193 : // reset the slot incase it is reused
194 0 : ::new (aSlot) Slot;
195 0 : memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16));
196 : // Update generation counter for debug
197 0 : aSlot->index(aSlot->index()+1);
198 : // update next pointer
199 0 : if (!m_freeSlots)
200 0 : aSlot->next(NULL);
201 : else
202 0 : aSlot->next(m_freeSlots);
203 0 : m_freeSlots = aSlot;
204 0 : }
205 :
206 : #ifndef GRAPHITE2_NSEGCACHE
207 : void Segment::splice(size_t offset, size_t length, Slot * startSlot,
208 : Slot * endSlot, const Slot * firstSpliceSlot,
209 : size_t numGlyphs)
210 : {
211 : const Slot * replacement = firstSpliceSlot;
212 : Slot * slot = startSlot;
213 : extendLength(numGlyphs - length);
214 : // insert extra slots if needed
215 : while (numGlyphs > length)
216 : {
217 : Slot * extra = newSlot();
218 : extra->prev(endSlot);
219 : extra->next(endSlot->next());
220 : endSlot->next(extra);
221 : if (extra->next())
222 : extra->next()->prev(extra);
223 : if (m_last == endSlot)
224 : m_last = extra;
225 : endSlot = extra;
226 : ++length;
227 : }
228 : // remove any extra
229 : if (numGlyphs < length)
230 : {
231 : Slot * afterSplice = endSlot->next();
232 : do
233 : {
234 : endSlot = endSlot->prev();
235 : freeSlot(endSlot->next());
236 : --length;
237 : } while (numGlyphs < length);
238 : endSlot->next(afterSplice);
239 : if (afterSplice)
240 : afterSplice->prev(endSlot);
241 : }
242 : assert(numGlyphs == length);
243 : // keep a record of consecutive slots wrt start of splice to minimize
244 : // iterative next/prev calls
245 : Slot * slotArray[eMaxSpliceSize];
246 : uint16 slotPosition = 0;
247 : for (uint16 i = 0; i < numGlyphs; i++)
248 : {
249 : if (slotPosition <= i)
250 : {
251 : slotArray[i] = slot;
252 : slotPosition = i;
253 : }
254 : slot->set(*replacement, offset, m_silf->numUser());
255 : if (replacement->attachedTo())
256 : {
257 : uint16 parentPos = replacement->attachedTo() - firstSpliceSlot;
258 : while (slotPosition < parentPos)
259 : {
260 : slotArray[slotPosition+1] = slotArray[slotPosition]->next();
261 : ++slotPosition;
262 : }
263 : slot->attachTo(slotArray[parentPos]);
264 : }
265 : if (replacement->nextSibling())
266 : {
267 : uint16 pos = replacement->nextSibling() - firstSpliceSlot;
268 : while (slotPosition < pos)
269 : {
270 : slotArray[slotPosition+1] = slotArray[slotPosition]->next();
271 : ++slotPosition;
272 : }
273 : slot->sibling(slotArray[pos]);
274 : }
275 : if (replacement->firstChild())
276 : {
277 : uint16 pos = replacement->firstChild() - firstSpliceSlot;
278 : while (slotPosition < pos)
279 : {
280 : slotArray[slotPosition+1] = slotArray[slotPosition]->next();
281 : ++slotPosition;
282 : }
283 : slot->child(slotArray[pos]);
284 : }
285 : slot = slot->next();
286 : replacement = replacement->next();
287 : }
288 : }
289 : #endif // GRAPHITE2_NSEGCACHE
290 :
291 0 : void Segment::linkClusters(Slot *s, Slot * end)
292 : {
293 0 : end = end->next();
294 :
295 0 : for (; s != end && !s->isBase(); s = s->next());
296 0 : Slot * ls = s;
297 :
298 0 : if (m_dir & 1)
299 : {
300 0 : for (; s != end; s = s->next())
301 : {
302 0 : if (!s->isBase()) continue;
303 :
304 0 : s->sibling(ls);
305 0 : ls = s;
306 : }
307 : }
308 : else
309 : {
310 0 : for (; s != end; s = s->next())
311 : {
312 0 : if (!s->isBase()) continue;
313 :
314 0 : ls->sibling(s);
315 0 : ls = s;
316 : }
317 : }
318 0 : }
319 :
320 0 : Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd)
321 : {
322 0 : Position currpos(0., 0.);
323 0 : Rect bbox;
324 0 : float cMin = 0.;
325 0 : float clusterMin = 0.;
326 :
327 0 : if (!iStart) iStart = m_first;
328 0 : if (!iEnd) iEnd = m_last;
329 :
330 0 : if (m_dir & 1)
331 : {
332 0 : for (Slot * s = iEnd, * const end = iStart->prev(); s && s != end; s = s->prev())
333 : {
334 0 : if (s->isBase())
335 0 : currpos = s->finalise(this, font, currpos, bbox, cMin, 0, clusterMin = currpos.x);
336 : }
337 : }
338 : else
339 : {
340 0 : for (Slot * s = iStart, * const end = iEnd->next(); s && s != end; s = s->next())
341 : {
342 0 : if (s->isBase())
343 0 : currpos = s->finalise(this, font, currpos, bbox, cMin, 0, clusterMin = currpos.x);
344 : }
345 : }
346 : return currpos;
347 : }
348 :
349 :
350 : template <typename utf_iter>
351 0 : inline void process_utf_data(Segment & seg, const Face & face, const int fid, utf_iter c, size_t n_chars)
352 : {
353 0 : const Cmap & cmap = face.cmap();
354 0 : int slotid = 0;
355 :
356 0 : const typename utf_iter::codeunit_type * const base = c;
357 0 : for (; n_chars; --n_chars, ++c, ++slotid)
358 : {
359 0 : const uint32 usv = *c;
360 0 : uint16 gid = cmap[usv];
361 0 : if (!gid) gid = face.findPseudo(usv);
362 0 : seg.appendSlot(slotid, usv, gid, fid, c - base);
363 : }
364 0 : }
365 :
366 :
367 0 : void Segment::read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void* pStart, size_t nChars)
368 : {
369 0 : assert(face);
370 0 : assert(pFeats);
371 :
372 0 : switch (enc)
373 : {
374 0 : case gr_utf8: process_utf_data(*this, *face, addFeatures(*pFeats), utf8::const_iterator(pStart), nChars); break;
375 0 : case gr_utf16: process_utf_data(*this, *face, addFeatures(*pFeats), utf16::const_iterator(pStart), nChars); break;
376 0 : case gr_utf32: process_utf_data(*this, *face, addFeatures(*pFeats), utf32::const_iterator(pStart), nChars); break;
377 : }
378 0 : }
379 :
380 0 : void Segment::prepare_pos(const Font * /*font*/)
381 : {
382 : // copy key changeable metrics into slot (if any);
383 0 : }
384 :
385 0 : void Segment::finalise(const Font *font)
386 : {
387 0 : if (!m_first) return;
388 :
389 0 : m_advance = positionSlots(font);
390 0 : int i = 0;
391 0 : for (Slot * s = m_first; s; s->index(i++), s = s->next())
392 : {
393 0 : int j = s->before();
394 0 : if (j < 0) continue;
395 :
396 0 : for (const int after = s->after(); j <= after; ++j)
397 : {
398 0 : CharInfo & c = *charinfo(j);
399 0 : if (c.before() == -1 || i < c.before()) c.before(i);
400 0 : if (c.after() < i) c.after(i);
401 : }
402 : }
403 0 : linkClusters(m_first, m_last);
404 : }
405 :
406 0 : void Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUSED justFlags flags, Slot *pFirst, Slot *pLast)
407 : {
408 0 : Slot *pEnd = pSlot;
409 : Slot *s, *end;
410 0 : int numBase = 0;
411 0 : float currWidth = 0.;
412 0 : float scale = font ? font->scale() : 1.0;
413 : float base;
414 :
415 0 : if (!pFirst) pFirst = pSlot;
416 0 : base = pFirst->origin().x / scale;
417 0 : width = width / scale;
418 0 : end = pLast ? pLast->next() : NULL;
419 :
420 0 : for (s = pFirst; s != end; s=s->next())
421 : {
422 0 : float w = s->origin().x / scale + s->advance() - base;
423 0 : if (w > currWidth) currWidth = w;
424 0 : pEnd = s;
425 0 : if (!s->attachedTo()) // what about trailing whitespace?
426 0 : numBase++;
427 : }
428 0 : if (pLast)
429 0 : while (s)
430 : {
431 0 : pEnd = s;
432 0 : s = s->next();
433 : }
434 : else
435 0 : pLast = pEnd;
436 :
437 0 : if (!numBase) return;
438 :
439 0 : Slot *oldFirst = m_first;
440 0 : Slot *oldLast = m_last;
441 : // add line end contextuals to linked list
442 0 : m_first = pSlot;
443 0 : m_last = pEnd;
444 : // process the various silf justification stuff returning updated currwidth
445 :
446 : // now fallback to spreading the remaining space among all the bases
447 0 : float nShift = (width - currWidth) / (numBase - 1);
448 0 : for (s = pFirst->nextSibling(); s != end; s = s->nextSibling())
449 0 : s->just(nShift + s->just());
450 0 : positionSlots(font, pSlot, pEnd);
451 :
452 0 : m_first = oldFirst;
453 0 : m_last = oldLast;
454 : // dump line end contextual markers
455 : }
456 :
457 : Slot *resolveExplicit(int level, int dir, Slot *s, int nNest = 0);
458 : void resolveWeak(int baseLevel, Slot *s);
459 : void resolveNeutrals(int baseLevel, Slot *s);
460 : void resolveImplicit(Slot *s, Segment *seg, uint8 aMirror);
461 : void resolveWhitespace(int baseLevel, Segment *seg, uint8 aBidi, Slot *s);
462 : Slot *resolveOrder(Slot * & s, const bool reordered, const int level = 0);
463 :
464 0 : void Segment::bidiPass(uint8 aBidi, int paradir, uint8 aMirror)
465 : {
466 0 : if (slotCount() == 0)
467 0 : return;
468 :
469 : Slot *s;
470 0 : int baseLevel = paradir ? 1 : 0;
471 0 : unsigned int bmask = 0;
472 0 : for (s = first(); s; s = s->next())
473 : {
474 0 : unsigned int bAttr = glyphAttr(s->gid(), aBidi);
475 0 : s->setBidiClass((bAttr <= 16) * bAttr);
476 0 : bmask |= (1 << s->getBidiClass());
477 0 : s->setBidiLevel(baseLevel);
478 : }
479 0 : if (bmask & (paradir ? 0x92 : 0x9C))
480 : {
481 0 : if (bmask & 0xF800)
482 0 : resolveExplicit(baseLevel, 0, first(), 0);
483 0 : if (bmask & 0x10178)
484 0 : resolveWeak(baseLevel, first());
485 0 : if (bmask & 0x161)
486 0 : resolveNeutrals(baseLevel, first());
487 0 : resolveImplicit(first(), this, aMirror);
488 0 : resolveWhitespace(baseLevel, this, aBidi, last());
489 0 : s = resolveOrder(s = first(), baseLevel);
490 0 : first(s); last(s->prev());
491 0 : s->prev()->next(0); s->prev(0);
492 : }
493 0 : else if (!(dir() & 4) && baseLevel && aMirror)
494 : {
495 0 : for (s = first(); s; s = s->next())
496 : {
497 0 : unsigned short g = glyphAttr(s->gid(), aMirror);
498 0 : if (g) s->setGlyph(this, g);
499 : }
500 : }
501 : }
502 :
|