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)  

Justifier.cpp
Go to the documentation of this file.
1 /* GRAPHITE2 LICENSING
2 
3  Copyright 2012, 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 
28 #include "inc/Segment.h"
29 #include "graphite2/Font.h"
30 #include "inc/debug.h"
31 #include "inc/CharInfo.h"
32 #include "inc/Slot.h"
33 #include "inc/Main.h"
34 #include <cmath>
35 
36 using namespace graphite2;
37 
38 class JustifyTotal {
39 public:
41  void accumulate(Slot *s, Segment *seg, int level);
42  int weight() const { return m_tWeight; }
43 
45 
46 private:
47  int m_numGlyphs;
48  int m_tStretch;
49  int m_tShrink;
50  int m_tStep;
51  int m_tWeight;
52 };
53 
55 {
56  ++m_numGlyphs;
57  m_tStretch += s->getJustify(seg, level, 0);
58  m_tShrink += s->getJustify(seg, level, 1);
59  m_tStep += s->getJustify(seg, level, 2);
60  m_tWeight += s->getJustify(seg, level, 3);
61 }
62 
63 float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUSED justFlags jflags, Slot *pFirst, Slot *pLast)
64 {
65  Slot *end = last();
66  float currWidth = 0.0;
67  const float scale = font ? font->scale() : 1.0f;
68  Position res;
69 
70  if (width < 0 && !(silf()->flags()))
71  return width;
72 
73  if ((m_dir & 1) != m_silf->dir() && m_silf->bidiPass() != m_silf->numPasses())
74  {
75  reverseSlots();
76  std::swap(pFirst, pLast);
77  }
78  if (!pFirst) pFirst = pSlot;
79  while (!pFirst->isBase()) pFirst = pFirst->attachedTo();
80  if (!pLast) pLast = last();
81  while (!pLast->isBase()) pLast = pLast->attachedTo();
82  const float base = pFirst->origin().x / scale;
83  width = width / scale;
84  if ((jflags & gr_justEndInline) == 0)
85  {
86  while (pLast != pFirst && pLast)
87  {
89  if (bbox.bl.x != 0.f || bbox.bl.y != 0.f || bbox.tr.x != 0.f || bbox.tr.y == 0.f)
90  break;
91  pLast = pLast->prev();
92  }
93  }
94 
95  if (pLast)
96  end = pLast->nextSibling();
97  if (pFirst)
98  pFirst = pFirst->nextSibling();
99 
100  int icount = 0;
101  int numLevels = silf()->numJustLevels();
102  if (!numLevels)
103  {
104  for (Slot *s = pSlot; s && s != end; s = s->nextSibling())
105  {
106  CharInfo *c = charinfo(s->before());
107  if (isWhitespace(c->unicodeChar()))
108  {
109  s->setJustify(this, 0, 3, 1);
110  s->setJustify(this, 0, 2, 1);
111  s->setJustify(this, 0, 0, -1);
112  ++icount;
113  }
114  }
115  if (!icount)
116  {
117  for (Slot *s = pSlot; s && s != end; s = s->nextSibling())
118  {
119  s->setJustify(this, 0, 3, 1);
120  s->setJustify(this, 0, 2, 1);
121  s->setJustify(this, 0, 0, -1);
122  }
123  }
124  ++numLevels;
125  }
126 
127  Vector<JustifyTotal> stats(numLevels);
128  for (Slot *s = pFirst; s && s != end; s = s->nextSibling())
129  {
130  float w = s->origin().x / scale + s->advance() - base;
131  if (w > currWidth) currWidth = w;
132  for (int j = 0; j < numLevels; ++j)
133  stats[j].accumulate(s, this, j);
134  s->just(0);
135  }
136 
137  for (int i = (width < 0.0f) ? -1 : numLevels - 1; i >= 0; --i)
138  {
139  float diff;
140  float error = 0.;
141  float diffpw;
142  int tWeight = stats[i].weight();
143  if (tWeight == 0) continue;
144 
145  do {
146  error = 0.;
147  diff = width - currWidth;
148  diffpw = diff / tWeight;
149  tWeight = 0;
150  for (Slot *s = pFirst; s && s != end; s = s->nextSibling()) // don't include final glyph
151  {
152  int w = s->getJustify(this, i, 3);
153  float pref = diffpw * w + error;
154  int step = s->getJustify(this, i, 2);
155  if (!step) step = 1; // handle lazy font developers
156  if (pref > 0)
157  {
158  float max = uint16(s->getJustify(this, i, 0));
159  if (i == 0) max -= s->just();
160  if (pref > max) pref = max;
161  else tWeight += w;
162  }
163  else
164  {
165  float max = uint16(s->getJustify(this, i, 1));
166  if (i == 0) max += s->just();
167  if (-pref > max) pref = -max;
168  else tWeight += w;
169  }
170  int actual = int(pref / step) * step;
171 
172  if (actual)
173  {
174  error += diffpw * w - actual;
175  if (i == 0)
176  s->just(s->just() + actual);
177  else
178  s->setJustify(this, i, 4, actual);
179  }
180  }
181  currWidth += diff - error;
182  } while (i == 0 && int(std::abs(error)) > 0 && tWeight);
183  }
184 
185  Slot *oldFirst = m_first;
186  Slot *oldLast = m_last;
187  if (silf()->flags() & 1)
188  {
189  m_first = pSlot = addLineEnd(pSlot);
190  m_last = pLast = addLineEnd(end);
191  if (!m_first || !m_last) return -1.0;
192  }
193  else
194  {
195  m_first = pSlot;
196  m_last = pLast;
197  }
198 
199  // run justification passes here
200 #if !defined GRAPHITE2_NTRACING
201  json * const dbgout = m_face->logger();
202  if (dbgout)
203  *dbgout << json::object
204  << "justifies" << objectid(this)
205  << "passes" << json::array;
206 #endif
207 
208  if (m_silf->justificationPass() != m_silf->positionPass() && (width >= 0.f || (silf()->flags() & 1)))
210 
211 #if !defined GRAPHITE2_NTRACING
212  if (dbgout)
213  {
214  *dbgout << json::item << json::close; // Close up the passes array
215  positionSlots(NULL, pSlot, pLast, m_dir);
216  Slot *lEnd = pLast->nextSibling();
217  *dbgout << "output" << json::array;
218  for(Slot * t = pSlot; t != lEnd; t = t->next())
219  *dbgout << dslot(this, t);
220  *dbgout << json::close << json::close;
221  }
222 #endif
223 
224  res = positionSlots(font, pSlot, pLast, m_dir);
225 
226  if (silf()->flags() & 1)
227  {
228  if (m_first)
230  if (m_last)
232  }
233  m_first = oldFirst;
234  m_last = oldLast;
235 
236  if ((m_dir & 1) != m_silf->dir() && m_silf->bidiPass() != m_silf->numPasses())
237  reverseSlots();
238  return res.x;
239 }
240 
242 {
243  Slot *eSlot = newSlot();
244  if (!eSlot) return NULL;
245  const uint16 gid = silf()->endLineGlyphid();
246  const GlyphFace * theGlyph = m_face->glyphs().glyphSafe(gid);
247  eSlot->setGlyph(this, gid, theGlyph);
248  if (nSlot)
249  {
250  eSlot->next(nSlot);
251  eSlot->prev(nSlot->prev());
252  nSlot->prev(eSlot);
253  eSlot->before(nSlot->before());
254  if (eSlot->prev())
255  eSlot->after(eSlot->prev()->after());
256  else
257  eSlot->after(nSlot->before());
258  }
259  else
260  {
261  nSlot = m_last;
262  eSlot->prev(nSlot);
263  nSlot->next(eSlot);
264  eSlot->after(eSlot->prev()->after());
265  eSlot->before(nSlot->after());
266  }
267  return eSlot;
268 }
269 
271 {
272  Slot *nSlot = s->next();
273  if (nSlot)
274  {
275  nSlot->prev(s->prev());
276  if (s->prev())
277  s->prev()->next(nSlot);
278  }
279  else
280  s->prev()->next(NULL);
281  freeSlot(s);
282 }
int level
Definition: afm2pl.c:1694
#define width(a)
Definition: aptex-macros.h:198
static void step(struct edge *edge)
int weight() const
Definition: Justifier.cpp:42
void accumulate(Slot *s, Segment *seg, int level)
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
Slot * last()
Definition: Segment.h:107
void freeSlot(Slot *)
Definition: Segment.cpp:140
const CharInfo * charinfo(unsigned int index) const
Definition: Segment.h:98
Position positionSlots(const Font *font=0, Slot *first=0, Slot *last=0, bool isRtl=false, bool isFinal=true)
Definition: Segment.cpp:288
const Face * m_face
Definition: Segment.h:171
void delLineEnd(Slot *s)
Definition: Justifier.cpp:270
uint8 flags() const
Definition: Segment.h:103
const Silf * m_silf
Definition: Segment.h:172
const Silf * silf() const
Definition: Segment.h:96
bool isWhitespace(const int cid) const
Definition: Segment.h:218
Slot * newSlot()
Definition: Segment.cpp:103
Slot * addLineEnd(Slot *nSlot)
Definition: Justifier.cpp:241
const Rect & theGlyphBBoxTemporary(uint16 gid) const
Definition: Segment.h:136
uint16 endLineGlyphid() const
Definition: Silf.h:100
uint8 bidiPass() const
Definition: Silf.h:92
uint8 numJustLevels() const
Definition: Silf.h:98
uint8 positionPass() const
Definition: Silf.h:90
uint8 numPasses() const
Definition: Silf.h:93
byte dir() const
Definition: Silf.h:97
bool runGraphite(Segment *seg, uint8 firstPass=0, uint8 lastPass=0, int dobidi=0) const
Definition: Silf.cpp:357
uint8 justificationPass() const
Definition: Silf.h:91
Slot * prev() const
Definition: Slot.h:86
Slot * nextSibling() const
Definition: Slot.h:126
Slot * next() const
Definition: Slot.h:84
bool isBase() const
Definition: Slot.h:97
uint16 glyph() const
Definition: Slot.h:88
int before() const
Definition: Slot.h:77
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
Position origin() const
Definition: Slot.h:73
static void close(json &)
Definition: json.cpp:108
static void array(json &)
Definition: json.cpp:110
static void object(json &)
Definition: json.cpp:109
static void item(json &)
Definition: json.cpp:111
int w
Definition: dviconv.c:26
#define error(a)
Definition: dviinfo.c:48
#define s
Definition: afcover.h:80
#define c(n)
Definition: gpos-common.c:150
int base
Definition: gsftopk.c:1502
#define NULL
Definition: ftobjs.h:61
small capitals from c petite p scientific i
Definition: afcover.h:80
char actual
Definition: exvar.h:12
unsigned short uint16
Definition: tiff.h:62
static struct statistic stats[]
Definition: lstatslib.c:289
Definition: bits.h:30
T max(const T a, const T b)
Definition: Main.h:152
@ gr_justEndInline
Definition: Segment.h:64
std::pair< const Segment *const, const Slot *const > dslot
Definition: debug.h:45
gr_uint16 uint16
Definition: Main.h:40
#define abs(a)
Definition: pbmplus.h:225
#define res(length)
Definition: picttoppm.c:287
double scale
Definition: pnmhistmap.c:38
#define GR_MAYBE_UNUSED
Definition: Main.h:172
#define CLASS_NEW_DELETE
Definition: Main.h:159
#define swap(sp)
Definition: interp.c:123
Definition: nsfix.c:44
Definition: pbmfont.h:11
Definition: sh2.c:920
Definition: gd.c:2418
Definition: dvips.h:235
struct t * next
Definition: dvips.h:237
int j
Definition: t4ht.c:1589
int diff
Definition: tex4ht.c:3815
return() int(((double) *(font_tbl[cur_fnt].wtbl+(int)(*(font_tbl[cur_fnt].char_wi+(int)(ch - font_tbl[cur_fnt].char_f)% 256)))/(double)(1L<< 20)) *(double) font_tbl[cur_fnt].scale)
#define end(cp)
Definition: zic.c:71