w32tex
About: TeX Live provides a comprehensive TeX system including all the major TeX-related programs, macro packages, and fonts that are free software. Windows sources.
  Fossies Dox: w32tex-src.tar.xz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

Segment.cpp
Go to the documentation of this file.
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 Segment::Segment(size_t numchars, const Face* face, uint32 script, int textDir)
46 : m_freeSlots(NULL),
47  m_freeJustifies(NULL),
48  m_charinfo(new CharInfo[numchars]),
49  m_collisions(NULL),
50  m_face(face),
51  m_silf(face->chooseSilf(script)),
52  m_first(NULL),
53  m_last(NULL),
54  m_bufSize(numchars + 10),
55  m_numGlyphs(numchars),
56  m_numCharinfo(numchars),
57  m_defaultOriginal(0),
58  m_dir(textDir),
59  m_flags(((m_silf->flags() & 0x20) != 0) << 1),
60  m_passBits(m_silf->aPassBits() ? -1 : 0)
61 {
62  freeSlot(newSlot());
63  m_bufSize = log_binary(numchars)+1;
64 }
65 
66 Segment::~Segment()
67 {
68  for (SlotRope::iterator i = m_slots.begin(); i != m_slots.end(); ++i)
69  free(*i);
71  free(*i);
73  free(*i);
74  delete[] m_charinfo;
76 }
77 
78 void Segment::appendSlot(int id, int cid, int gid, int iFeats, size_t coffset)
79 {
80  Slot *aSlot = newSlot();
81 
82  if (!aSlot) return;
83  m_charinfo[id].init(cid);
84  m_charinfo[id].feats(iFeats);
85  m_charinfo[id].base(coffset);
86  const GlyphFace * theGlyph = m_face->glyphs().glyphSafe(gid);
87  m_charinfo[id].breakWeight(theGlyph ? theGlyph->attrs()[m_silf->aBreak()] : 0);
88 
89  aSlot->child(NULL);
90  aSlot->setGlyph(this, gid, theGlyph);
91  aSlot->originate(id);
92  aSlot->before(id);
93  aSlot->after(id);
94  if (m_last) m_last->next(aSlot);
95  aSlot->prev(m_last);
96  m_last = aSlot;
97  if (!m_first) m_first = aSlot;
98  if (theGlyph && m_silf->aPassBits())
99  m_passBits &= theGlyph->attrs()[m_silf->aPassBits()]
100  | (m_silf->numPasses() > 16 ? (theGlyph->attrs()[m_silf->aPassBits() + 1] << 16) : 0);
101 }
102 
104 {
105  if (!m_freeSlots)
106  {
107  // check that the segment doesn't grow indefinintely
109  return NULL;
110  int numUser = m_silf->numUser();
111 #if !defined GRAPHITE2_NTRACING
112  if (m_face->logger()) ++numUser;
113 #endif
114  Slot *newSlots = grzeroalloc<Slot>(m_bufSize);
115  int16 *newAttrs = grzeroalloc<int16>(m_bufSize * numUser);
116  if (!newSlots || !newAttrs)
117  {
118  free(newSlots);
119  free(newAttrs);
120  return NULL;
121  }
122  for (size_t i = 0; i < m_bufSize; i++)
123  {
124  ::new (newSlots + i) Slot(newAttrs + i * numUser);
125  newSlots[i].next(newSlots + i + 1);
126  }
127  newSlots[m_bufSize - 1].next(NULL);
128  newSlots[0].next(NULL);
129  m_slots.push_back(newSlots);
130  m_userAttrs.push_back(newAttrs);
131  m_freeSlots = (m_bufSize > 1)? newSlots + 1 : NULL;
132  return newSlots;
133  }
134  Slot *res = m_freeSlots;
136  res->next(NULL);
137  return res;
138 }
139 
140 void Segment::freeSlot(Slot *aSlot)
141 {
142  if (aSlot == nullptr) return;
143  if (m_last == aSlot) m_last = aSlot->prev();
144  if (m_first == aSlot) m_first = aSlot->next();
145  if (aSlot->attachedTo())
146  aSlot->attachedTo()->removeChild(aSlot);
147  while (aSlot->firstChild())
148  {
149  if (aSlot->firstChild()->attachedTo() == aSlot)
150  {
151  aSlot->firstChild()->attachTo(nullptr);
152  aSlot->removeChild(aSlot->firstChild());
153  }
154  else
155  aSlot->firstChild(nullptr);
156  }
157  // reset the slot incase it is reused
158  ::new (aSlot) Slot(aSlot->userAttrs());
159  memset(aSlot->userAttrs(), 0, m_silf->numUser() * sizeof(int16));
160  // Update generation counter for debug
161 #if !defined GRAPHITE2_NTRACING
162  if (m_face->logger())
163  ++aSlot->userAttrs()[m_silf->numUser()];
164 #endif
165  // update next pointer
166  if (!m_freeSlots)
167  aSlot->next(nullptr);
168  else
169  aSlot->next(m_freeSlots);
170  m_freeSlots = aSlot;
171 }
172 
174 {
175  if (!m_freeJustifies)
176  {
177  const size_t justSize = SlotJustify::size_of(m_silf->numJustLevels());
178  byte *justs = grzeroalloc<byte>(justSize * m_bufSize);
179  if (!justs) return NULL;
180  for (ptrdiff_t i = m_bufSize - 2; i >= 0; --i)
181  {
182  SlotJustify *p = reinterpret_cast<SlotJustify *>(justs + justSize * i);
183  SlotJustify *next = reinterpret_cast<SlotJustify *>(justs + justSize * (i + 1));
184  p->next = next;
185  }
186  m_freeJustifies = (SlotJustify *)justs;
188  }
191  res->next = NULL;
192  return res;
193 }
194 
195 void Segment::freeJustify(SlotJustify *aJustify)
196 {
197  int numJust = m_silf->numJustLevels();
198  if (m_silf->numJustLevels() <= 0) numJust = 1;
199  aJustify->next = m_freeJustifies;
200  memset(aJustify->values, 0, numJust*SlotJustify::NUMJUSTPARAMS*sizeof(int16));
201  m_freeJustifies = aJustify;
202 }
203 
204 // reverse the slots but keep diacritics in their same position after their bases
206 {
207  m_dir = m_dir ^ 64; // invert the reverse flag
208  if (m_first == m_last) return; // skip 0 or 1 glyph runs
209 
210  Slot *t = 0;
211  Slot *curr = m_first;
212  Slot *tlast;
213  Slot *tfirst;
214  Slot *out = 0;
215 
216  while (curr && getSlotBidiClass(curr) == 16)
217  curr = curr->next();
218  if (!curr) return;
219  tfirst = curr->prev();
220  tlast = curr;
221 
222  while (curr)
223  {
224  if (getSlotBidiClass(curr) == 16)
225  {
226  Slot *d = curr->next();
227  while (d && getSlotBidiClass(d) == 16)
228  d = d->next();
229 
230  d = d ? d->prev() : m_last;
231  Slot *p = out->next(); // one after the diacritics. out can't be null
232  if (p)
233  p->prev(d);
234  else
235  tlast = d;
236  t = d->next();
237  d->next(p);
238  curr->prev(out);
239  out->next(curr);
240  }
241  else // will always fire first time round the loop
242  {
243  if (out)
244  out->prev(curr);
245  t = curr->next();
246  curr->next(out);
247  out = curr;
248  }
249  curr = t;
250  }
251  out->prev(tfirst);
252  if (tfirst)
253  tfirst->next(out);
254  else
255  m_first = out;
256  m_last = tlast;
257 }
258 
260 {
261  end = end->next();
262 
263  for (; s != end && !s->isBase(); s = s->next());
264  Slot * ls = s;
265 
266  if (m_dir & 1)
267  {
268  for (; s != end; s = s->next())
269  {
270  if (!s->isBase()) continue;
271 
272  s->sibling(ls);
273  ls = s;
274  }
275  }
276  else
277  {
278  for (; s != end; s = s->next())
279  {
280  if (!s->isBase()) continue;
281 
282  ls->sibling(s);
283  ls = s;
284  }
285  }
286 }
287 
288 Position Segment::positionSlots(const Font *font, Slot * iStart, Slot * iEnd, bool isRtl, bool isFinal)
289 {
290  Position currpos(0., 0.);
291  float clusterMin = 0.;
292  Rect bbox;
293  bool reorder = (currdir() != isRtl);
294 
295  if (reorder)
296  {
297  Slot *temp;
298  reverseSlots();
299  temp = iStart;
300  iStart = iEnd;
301  iEnd = temp;
302  }
303  if (!iStart) iStart = m_first;
304  if (!iEnd) iEnd = m_last;
305 
306  if (!iStart || !iEnd) // only true for empty segments
307  return currpos;
308 
309  if (isRtl)
310  {
311  for (Slot * s = iEnd, * const end = iStart->prev(); s && s != end; s = s->prev())
312  {
313  if (s->isBase())
314  currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isRtl, isFinal);
315  }
316  }
317  else
318  {
319  for (Slot * s = iStart, * const end = iEnd->next(); s && s != end; s = s->next())
320  {
321  if (s->isBase())
322  currpos = s->finalise(this, font, currpos, bbox, 0, clusterMin = currpos.x, isRtl, isFinal);
323  }
324  }
325  if (reorder)
326  reverseSlots();
327  return currpos;
328 }
329 
330 
331 void Segment::associateChars(int offset, size_t numChars)
332 {
333  int i = 0, j = 0;
334  CharInfo *c, *cend;
335  for (c = m_charinfo + offset, cend = m_charinfo + offset + numChars; c != cend; ++c)
336  {
337  c->before(-1);
338  c->after(-1);
339  }
340  for (Slot * s = m_first; s; s->index(i++), s = s->next())
341  {
342  j = s->before();
343  if (j < 0) continue;
344 
345  for (const int after = s->after(); j <= after; ++j)
346  {
347  c = charinfo(j);
348  if (c->before() == -1 || i < c->before()) c->before(i);
349  if (c->after() < i) c->after(i);
350  }
351  }
352  for (Slot *s = m_first; s; s = s->next())
353  {
354  int a;
355  for (a = s->after() + 1; a < offset + int(numChars) && charinfo(a)->after() < 0; ++a)
356  { charinfo(a)->after(s->index()); }
357  --a;
358  s->after(a);
359 
360  for (a = s->before() - 1; a >= offset && charinfo(a)->before() < 0; --a)
361  { charinfo(a)->before(s->index()); }
362  ++a;
363  s->before(a);
364  }
365 }
366 
367 
368 template <typename utf_iter>
369 inline void process_utf_data(Segment & seg, const Face & face, const int fid, utf_iter c, size_t n_chars)
370 {
371  const Cmap & cmap = face.cmap();
372  int slotid = 0;
373 
374  const typename utf_iter::codeunit_type * const base = c;
375  for (; n_chars; --n_chars, ++c, ++slotid)
376  {
377  const uint32 usv = *c;
378  uint16 gid = cmap[usv];
379  if (!gid) gid = face.findPseudo(usv);
380  seg.appendSlot(slotid, usv, gid, fid, c - base);
381  }
382 }
383 
384 
385 bool Segment::read_text(const Face *face, const Features* pFeats/*must not be NULL*/, gr_encform enc, const void* pStart, size_t nChars)
386 {
387  assert(face);
388  assert(pFeats);
389  if (!m_charinfo) return false;
390 
391  // utf iterator is self recovering so we don't care about the error state of the iterator.
392  switch (enc)
393  {
394  case gr_utf8: process_utf_data(*this, *face, addFeatures(*pFeats), utf8::const_iterator(pStart), nChars); break;
395  case gr_utf16: process_utf_data(*this, *face, addFeatures(*pFeats), utf16::const_iterator(pStart), nChars); break;
396  case gr_utf32: process_utf_data(*this, *face, addFeatures(*pFeats), utf32::const_iterator(pStart), nChars); break;
397  }
398  return true;
399 }
400 
401 void Segment::doMirror(uint16 aMirror)
402 {
403  Slot * s;
404  for (s = m_first; s; s = s->next())
405  {
406  unsigned short g = glyphAttr(s->gid(), aMirror);
407  if (g && (!(dir() & 4) || !glyphAttr(s->gid(), aMirror + 1)))
408  s->setGlyph(this, g);
409  }
410 }
411 
413 {
414  m_collisions = grzeroalloc<SlotCollision>(slotCount());
415  if (!m_collisions) return false;
416 
417  for (Slot *p = m_first; p; p = p->next())
418  if (p->index() < slotCount())
419  ::new (collisionInfo(p)) SlotCollision(this, p);
420  else
421  return false;
422  return true;
423 }
int ptrdiff_t
Definition: CPAL.d:3845
#define next(a)
Definition: aptex-macros.h:924
#define before
Definition: aptex-macros.h:256
void init(int cid)
Definition: CharInfo.h:38
int after() const
Definition: CharInfo.h:44
int before() const
Definition: CharInfo.h:46
size_t base() const
Definition: CharInfo.h:48
int breakWeight() const
Definition: CharInfo.h:42
void feats(int offset)
Definition: CharInfo.h:40
const GlyphCache & glyphs() const
Definition: Face.h:150
json * logger() const
Definition: Face.h:162
const GlyphFace * glyphSafe(unsigned short glyphid) const
Definition: GlyphCache.h:154
const sparse & attrs() const
Definition: GlyphFace.h:53
bool initCollisions()
Definition: Segment.cpp:412
SlotCollision * m_collisions
Definition: Segment.h:170
void linkClusters(Slot *first, Slot *last)
Definition: Segment.cpp:259
void freeSlot(Slot *)
Definition: Segment.cpp:140
int8 getSlotBidiClass(Slot *s) const
Definition: Segment.h:185
size_t m_bufSize
Definition: Segment.h:175
void doMirror(uint16 aMirror)
Definition: Segment.cpp:401
AttributeRope m_userAttrs
Definition: Segment.h:164
SlotRope m_slots
Definition: Segment.h:163
size_t slotCount() const
Definition: Segment.h:91
const CharInfo * charinfo(unsigned int index) const
Definition: Segment.h:98
JustifyRope m_justifies
Definition: Segment.h:165
bool currdir() const
Definition: Segment.h:130
Position positionSlots(const Font *font=0, Slot *first=0, Slot *last=0, bool isRtl=false, bool isFinal=true)
Definition: Segment.cpp:288
size_t m_numGlyphs
Definition: Segment.h:176
size_t m_numCharinfo
Definition: Segment.h:177
SlotJustify * m_freeJustifies
Definition: Segment.h:168
bool read_text(const Face *face, const Features *pFeats, gr_encform enc, const void *pStart, size_t nChars)
Definition: Segment.cpp:385
void associateChars(int offset, size_t num)
Definition: Segment.cpp:331
const Face * m_face
Definition: Segment.h:171
CharInfo * m_charinfo
Definition: Segment.h:169
Slot * m_freeSlots
Definition: Segment.h:167
int addFeatures(const Features &feats)
Definition: Segment.h:119
int8 dir() const
Definition: Segment.h:128
const Silf * m_silf
Definition: Segment.h:172
int16 glyphAttr(uint16 gid, uint16 gattr) const
Definition: Segment.h:133
Slot * newSlot()
Definition: Segment.cpp:103
SlotCollision * collisionInfo(const Slot *s) const
Definition: Segment.h:152
SlotJustify * newJustify()
Definition: Segment.cpp:173
void appendSlot(int i, int cid, int gid, int fid, size_t coffset)
Definition: Segment.cpp:78
void freeJustify(SlotJustify *aJustify)
Definition: Segment.cpp:195
uint8 aPassBits() const
Definition: Silf.h:86
uint8 numJustLevels() const
Definition: Silf.h:98
uint8 aBreak() const
Definition: Silf.h:84
uint8 numPasses() const
Definition: Silf.h:93
uint8 numUser() const
Definition: Silf.h:82
Slot * prev() const
Definition: Slot.h:86
bool child(Slot *ap)
Definition: Slot.cpp:408
Slot * firstChild() const
Definition: Slot.h:123
bool sibling(Slot *ap)
Definition: Slot.cpp:419
Slot * next() const
Definition: Slot.h:84
void originate(int ind)
Definition: Slot.h:93
int before() const
Definition: Slot.h:77
int16 * userAttrs() const
Definition: Slot.h:112
int after() const
Definition: Slot.h:78
Slot * attachedTo() const
Definition: Slot.h:121
void setGlyph(Segment *seg, uint16 glyphid, const GlyphFace *theGlyph=NULL)
Definition: Slot.cpp:452
void attachTo(Slot *ap)
Definition: Slot.h:120
bool removeChild(Slot *ap)
Definition: Slot.cpp:430
iterator begin()
Definition: List.h:63
iterator end()
Definition: List.h:66
void push_back(const T &v)
Definition: List.h:91
#define free(a)
Definition: decNumber.cpp:310
static int id
Definition: bifont.c:66
char * temp
Definition: dvidvi.c:137
#define s
Definition: afcover.h:80
#define t
Definition: afcover.h:96
static FIELD_PTR curr
Definition: genind.c:35
#define c(n)
Definition: gpos-common.c:150
#define a(n)
Definition: gpos-common.c:148
#define d(n)
Definition: gpos-common.c:151
int base
Definition: gsftopk.c:1502
FILE * out
Definition: hbf2gf.c:286
assert(pcxLoadImage24((char *)((void *) 0), fp, pinfo, hdr))
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p
Definition: afcover.h:72
small capitals from c petite p scientific i
Definition: afcover.h:80
xD9 x84 xD8 xAD xD9 x80 xF0 x90 xAC x9A xE0 xA7 xA6 xE0 xA7 xAA xF0 x91 x84 xA4 xF0 x91 x84 x89 xF0 x91 x84 x9B xF0 x90 x8A xAB xF0 x90 x8B x89 xE2 xB2 x9E xE2 xB2 x9F xD0 xBE xD0 x9E xF0 x90 x90 x84 xF0 x90 x90 xAC xE1 x83 x98 xE1 x83 x94 xE1 x83 x90 xE1 xB2 xBF xE2 xB0 x95 xE2 xB1 x85 xCE xBF xCE x9F xE0 xA8 xA0 xE0 xA8 xB0 xE0 xA9 xA6 Kayah xEA xA4 x8D xEA xA4 x80 Khmer xE1 xA7 xA1 xE1 xA7 xAA xE0 xBB x90 Latin Subscript xE2 x82 x92 xE2 x82 x80 xEA x93 xB3 xF0 x96 xB9 xA1 xF0 x96 xB9 x9B xF0 x96 xB9 xAF xE1 x80 x9D xE1 x80 x84 xE1 x80 x82 no script
Definition: afscript.h:271
FT_BBox bbox
Definition: ftbbox.c:467
FT_Face face
Definition: cffdrivr.c:659
void * new(uint32_t size)
Definition: mem.c:34
unsigned short uint16
Definition: tiff.h:62
short int16
Definition: tiff.h:61
unsigned long uint32
Definition: tiff.h:68
Definition: bits.h:30
unsigned int log_binary(T v)
Definition: bits.h:124
#define res(length)
Definition: picttoppm.c:287
int g
Definition: ppmqvga.c:68
static int offset
Definition: ppmtogif.c:642
bstring c int memset(void *s, int c, int length)
static char * cend
Definition: pscolor.c:51
gr_encform
Definition: Types.h:39
@ gr_utf16
Definition: Types.h:40
@ gr_utf32
Definition: Types.h:40
@ gr_utf8
Definition: Types.h:40
void process_utf_data(Segment &seg, const Face &face, const int fid, utf_iter c, size_t n_chars)
Definition: Segment.cpp:369
#define flags
#define MAX_SEG_GROWTH_FACTOR
Definition: Segment.h:43
Slot * newSlot
Definition: opcodes.h:274
Definition: nsfix.c:44
Definition: pbmfont.h:11
static size_t size_of(size_t levels)
Definition: Slot.h:50
static const int NUMJUSTPARAMS
Definition: Slot.h:44
SlotJustify * next
Definition: Slot.h:54
int16 values[1]
Definition: Slot.h:55
Definition: sh2.c:920
Definition: gd.c:2418
Definition: dvips.h:235
int j
Definition: t4ht.c:1589
@ after
Definition: texnodes.h:374
TT_CharMap cmap
Definition: ttf2pfb.c:163
#define end(cp)
Definition: zic.c:71