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)  

lookups.c
Go to the documentation of this file.
1 /* -*- coding: utf-8 -*- */
2 /* Copyright (C) 2007-2012 by George Williams */
3 /*
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6 
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9 
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13 
14  * The name of the author may not be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16 
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
20  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
23  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
25  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
26  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 #include "fontforgevw.h"
29 
30 static int uint32_cmp(const void *_ui1, const void *_ui2) {
31  if ( *(uint32 *) _ui1 > *(uint32 *)_ui2 )
32 return( 1 );
33  if ( *(uint32 *) _ui1 < *(uint32 *)_ui2 )
34 return( -1 );
35 
36 return( 0 );
37 }
38 
39 static int lang_cmp(const void *_ui1, const void *_ui2) {
40  /* The default language is magic, and should come first in the list even */
41  /* if that is not true alphabetical order */
42  if ( *(uint32 *) _ui1 == DEFAULT_LANG )
43 return( -1 );
44  if ( *(uint32 *) _ui2 == DEFAULT_LANG )
45 return( 1 );
46 
47  if ( *(uint32 *) _ui1 > *(uint32 *)_ui2 )
48 return( 1 );
49  if ( *(uint32 *) _ui1 < *(uint32 *)_ui2 )
50 return( -1 );
51 
52 return( 0 );
53 }
54 
56  /* Presumes that either SFFindUnusedLookups or SFFindClearUnusedLookupBits */
57  /* has been called first */
58  /* Since MS will sometimes ignore a script if it isn't found in both */
59  /* GPOS and GSUB we want to return the same script list no matter */
60  /* what the setting of gpos ... so we totally ignore that argument */
61  /* and always look at both sets of lookups */
62 
63 /* Sergey Malkin from MicroSoft tells me:
64  Each shaping engine in Uniscribe can decide on its requirements for
65  layout tables - some of them require both GSUB and GPOS, in some cases
66  any table present is enough, or it can work without any table.
67 
68  Sometimes, purpose of the check is to determine if font is supporting
69  particular script - if required tables are not there font is just
70  rejected by this shaping engine. Sometimes, shaping engine can not just
71  reject the font because there are fonts using older shaping technologies
72  we still have to support, so it uses some logic when to fallback to
73  legacy layout code.
74 
75  In your case this is Hebrew, where both tables are required to use
76  OpenType processing. Arabic requires both tables too, Latin requires
77  GSUB to execute GPOS. But in general, if you have both tables you should
78  be safe with any script to get fully featured OpenType shaping.
79 
80 In other words, if we have a Hebrew font with just GPOS features they won't work,
81 and MS will not use the font at all. We must add a GSUB table. In the unlikely
82 event that we had a hebrew font with only GSUB it would not work either.
83 
84 So if we want our lookups to have a chance of executing under Uniscribe we
85 better make sure that both tables have the same script set.
86 
87 (Sergey says we could optimize a little: A Latin GSUB table will run without
88 a GPOS, but he says the GPOS won't work without a GSUB.)
89 */
90  int cnt=0, tot=0, i;
91  uint32 *scripts = NULL;
92  OTLookup *test;
94  struct scriptlanglist *sl;
95 
96  /* So here always give scripts for both (see comment above) no */
97  /* matter what they asked for */
98  for ( gpos=0; gpos<2; ++gpos ) {
99  for ( test = gpos ? sf->gpos_lookups : sf->gsub_lookups; test!=NULL; test = test->next ) {
100  if ( test->unused )
101  continue;
102  for ( fl=test->features; fl!=NULL; fl=fl->next ) {
103  if ( fl->ismac )
104  continue;
105  for ( sl=fl->scripts ; sl!=NULL; sl=sl->next ) {
106  for ( i=0; i<cnt; ++i ) {
107  if ( sl->script==scripts[i] )
108  break;
109  }
110  if ( i==cnt ) {
111  if ( cnt>=tot )
112  scripts = realloc(scripts,(tot+=10)*sizeof(uint32));
113  scripts[cnt++] = sl->script;
114  }
115  }
116  }
117  }
118  }
119 
120  if ( cnt==0 )
121 return( NULL );
122 
123  /* We want our scripts in alphabetic order */
124  qsort(scripts,cnt,sizeof(uint32),uint32_cmp);
125  /* add a 0 entry to mark the end of the list */
126  if ( cnt>=tot )
127  scripts = realloc(scripts,(tot+1)*sizeof(uint32));
128  scripts[cnt] = 0;
129 return( scripts );
130 }
131 
133  /* However, the language lists (I think) are distinct */
134  /* But giving a value of -1 for gpos will give us the set of languages in */
135  /* both tables (for this script) */
136  int cnt=0, tot=0, i, g, l;
137  uint32 *langs = NULL;
138  OTLookup *test;
140  struct scriptlanglist *sl;
141 
142  for ( g=0; g<2; ++g ) {
143  if (( gpos==0 && g==1 ) || ( gpos==1 && g==0 ))
144  continue;
145  for ( test = g ? sf->gpos_lookups : sf->gsub_lookups; test!=NULL; test = test->next ) {
146  if ( test->unused )
147  continue;
148  for ( fl=test->features; fl!=NULL; fl=fl->next ) {
149  for ( sl=fl->scripts ; sl!=NULL; sl=sl->next ) {
150  if ( sl->script==script ) {
151  for ( l=0; l<sl->lang_cnt; ++l ) {
152  uint32 lang;
153  if ( l<MAX_LANG )
154  lang = sl->langs[l];
155  else
156  lang = sl->morelangs[l-MAX_LANG];
157  for ( i=0; i<cnt; ++i ) {
158  if ( lang==langs[i] )
159  break;
160  }
161  if ( i==cnt ) {
162  if ( cnt>=tot )
163  langs = realloc(langs,(tot+=10)*sizeof(uint32));
164  langs[cnt++] = lang;
165  }
166  }
167  }
168  }
169  }
170  }
171  }
172 
173  if ( cnt==0 ) {
174  /* We add dummy script entries. Because Uniscribe will refuse to */
175  /* process some scripts if they don't have an entry in both GPOS */
176  /* an GSUB. So if a script appears in either table, force it to */
177  /* appear in both. That means we can get scripts with no lookups */
178  /* and hence no languages. It seems that Uniscribe doesn't like */
179  /* that either. So give each such script a dummy default language */
180  /* entry. This is what VOLT does */
181  langs = calloc(2,sizeof(uint32));
182  langs[0] = DEFAULT_LANG;
183 return( langs );
184  }
185 
186  /* We want our languages in alphabetic order */
187  qsort(langs,cnt,sizeof(uint32),lang_cmp);
188  /* add a 0 entry to mark the end of the list */
189  if ( cnt>=tot )
190  langs = realloc(langs,(tot+1)*sizeof(uint32));
191  langs[cnt] = 0;
192 return( langs );
193 }
194 
196  int cnt=0, tot=0, i, l, isg;
197  uint32 *features = NULL;
198  OTLookup *test;
200  struct scriptlanglist *sl;
201  /* gpos==0 => GSUB, gpos==1 => GPOS, gpos==-1 => both, gpos==-2 => Both & morx & kern */
202 
203  if ( sf->cidmaster ) sf=sf->cidmaster;
204  for ( isg = 0; isg<2; ++isg ) {
205  if ( gpos>=0 && isg!=gpos )
206  continue;
207  for ( test = isg ? sf->gpos_lookups : sf->gsub_lookups; test!=NULL; test = test->next ) {
208  if ( test->unused )
209  continue;
210  for ( fl=test->features; fl!=NULL; fl=fl->next ) {
211  if ( fl->ismac && gpos!=-2 )
212  continue;
213  if ( script==0xffffffff ) {
214  for ( i=0; i<cnt; ++i ) {
215  if ( fl->featuretag==features[i] )
216  break;
217  }
218  if ( i==cnt ) {
219  if ( cnt>=tot )
220  features = realloc(features,(tot+=10)*sizeof(uint32));
221  features[cnt++] = fl->featuretag;
222  }
223  } else for ( sl=fl->scripts ; sl!=NULL; sl=sl->next ) {
224  if ( sl->script==script ) {
225  int matched = false;
226  if ( fl->ismac && gpos==-2 )
227  matched = true;
228  else for ( l=0; l<sl->lang_cnt; ++l ) {
229  uint32 testlang;
230  if ( l<MAX_LANG )
231  testlang = sl->langs[l];
232  else
233  testlang = sl->morelangs[l-MAX_LANG];
234  if ( testlang==lang ) {
235  matched = true;
236  break;
237  }
238  }
239  if ( matched ) {
240  for ( i=0; i<cnt; ++i ) {
241  if ( fl->featuretag==features[i] )
242  break;
243  }
244  if ( i==cnt ) {
245  if ( cnt>=tot )
246  features = realloc(features,(tot+=10)*sizeof(uint32));
247  features[cnt++] = fl->featuretag;
248  }
249  }
250  }
251  }
252  }
253  }
254  }
255 
256  if ( sf->design_size!=0 && gpos ) {
257  /* The 'size' feature is like no other. It has no lookups and so */
258  /* we will never find it in the normal course of events. If the */
259  /* user has specified a design size, then every script/lang combo */
260  /* gets a 'size' feature which contains no lookups but feature */
261  /* params */
262  if ( cnt>=tot )
263  features = realloc(features,(tot+=2)*sizeof(uint32));
264  features[cnt++] = CHR('s','i','z','e');
265  }
266 
267  if ( cnt==0 )
268 return( calloc(1,sizeof(uint32)) );
269 
270  /* We don't care if our features are in alphabetical order here */
271  /* all that matters is whether the complete list of features is */
272  /* ordering here would be irrelevant */
273  /* qsort(features,cnt,sizeof(uint32),uint32_cmp); */
274 
275  /* add a 0 entry to mark the end of the list */
276  if ( cnt>=tot )
277  features = realloc(features,(tot+1)*sizeof(uint32));
278  features[cnt] = 0;
279 return( features );
280 }
281 
283  int cnt=0, tot=0, l;
284  OTLookup **lookups = NULL;
285  OTLookup *test;
287  struct scriptlanglist *sl;
288 
289  for ( test = gpos ? sf->gpos_lookups : sf->gsub_lookups; test!=NULL; test = test->next ) {
290  if ( test->unused )
291  continue;
292  for ( fl=test->features; fl!=NULL; fl=fl->next ) {
293  if ( fl->featuretag==feature ) {
294  for ( sl=fl->scripts ; sl!=NULL; sl=sl->next ) {
295  if ( sl->script==script ) {
296  for ( l=0; l<sl->lang_cnt; ++l ) {
297  uint32 testlang;
298  if ( l<MAX_LANG )
299  testlang = sl->langs[l];
300  else
301  testlang = sl->morelangs[l-MAX_LANG];
302  if ( testlang==lang ) {
303  if ( cnt>=tot )
304  lookups = realloc(lookups,(tot+=10)*sizeof(OTLookup *));
305  lookups[cnt++] = test;
306  goto found;
307  }
308  }
309  }
310  }
311  }
312  }
313  found:;
314  }
315 
316  if ( cnt==0 )
317 return( NULL );
318 
319  /* lookup order is irrelevant here. might as well leave it in invocation order */
320  /* add a 0 entry to mark the end of the list */
321  if ( cnt>=tot )
322  lookups = realloc(lookups,(tot+1)*sizeof(OTLookup *));
323  lookups[cnt] = 0;
324 return( lookups );
325 }
326 
327 static int LigaturesFirstComponentGID(SplineFont *sf,char *components) {
328  int gid, ch;
329  char *pt;
330 
331  for ( pt = components; *pt!='\0' && *pt!=' '; ++pt );
332  ch = *pt; *pt = '\0';
333  gid = SFFindExistingSlot(sf,-1,components);
334  *pt = ch;
335 return( gid );
336 }
337 
338 static int PSTValid(SplineFont *sf,PST *pst) {
339  char *start, *pt, ch;
340  int ret;
341 
342  switch ( pst->type ) {
343  case pst_position:
344 return( true );
345  case pst_pair:
346 return( SCWorthOutputting(SFGetChar(sf,-1,pst->u.pair.paired)) );
348  case pst_ligature:
349  for ( start = pst->u.mult.components; *start ; ) {
350  for ( pt=start; *pt && *pt!=' '; ++pt );
351  ch = *pt; *pt = '\0';
353  if ( !ret ) {
354  LogError(_("Lookup subtable contains unused glyph %s making the whole subtable invalid"), start);
355  *pt = ch;
356 return( false );
357  }
358  *pt = ch;
359  if ( ch==0 )
360  start = pt;
361  else
362  start = pt+1;
363  }
364  default:
365  break;
366  }
367 return( true );
368 }
369 
371  uint8 *used = calloc(sf->glyphcnt,sizeof(uint8));
372  SplineChar **glyphs, *sc;
373  int i, k, gid, cnt;
374  KernPair *kp;
375  PST *pst;
376  int ispair = subtable->lookup->lookup_type == gpos_pair;
377  int isliga = subtable->lookup->lookup_type == gsub_ligature;
378 
379  for ( i=0; i<sf->glyphcnt; ++i ) if ( SCWorthOutputting(sc = sf->glyphs[i]) ) {
380  if ( ispair ) {
381  for ( k=0; k<2; ++k ) {
382  for ( kp= k ? sc->kerns : sc->vkerns; kp!=NULL ; kp=kp->next ) {
383  if ( !SCWorthOutputting(kp->sc))
384  continue;
385  if ( kp->subtable == subtable ) {
386  used[i] = true;
387  goto continue_;
388  }
389  }
390  }
391  }
392  for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
393  if ( pst->subtable == subtable && PSTValid(sf,pst)) {
394  if ( !isliga ) {
395  used[i] = true;
396  goto continue_;
397  } else {
398  gid = LigaturesFirstComponentGID(sf,pst->u.lig.components);
399  pst->u.lig.lig = sc;
400  if ( gid!=-1 )
401  used[gid] = true;
402  /* can't continue here. ffi might be "f+f+i" and "ff+i" */
403  /* and we need to mark both "f" and "ff" as used */
404  }
405  }
406  }
407  continue_: ;
408  }
409 
410  for ( i=cnt=0 ; i<sf->glyphcnt; ++i )
411  if ( used[i] )
412  ++cnt;
413 
414  if ( cnt==0 ) {
415  free(used);
416 return( NULL );
417  }
418  glyphs = malloc((cnt+1)*sizeof(SplineChar *));
419  for ( i=cnt=0 ; i<sf->glyphcnt; ++i ) {
420  if ( used[i] )
421  glyphs[cnt++] = sf->glyphs[i];
422  }
423  glyphs[cnt] = NULL;
424  free(used);
425 return( glyphs );
426 }
427 
428 static void TickLookupKids(OTLookup *otl) {
429  struct lookup_subtable *sub;
430  int i,j;
431 
432  for ( sub=otl->subtables; sub!=NULL; sub=sub->next ) {
433  if ( sub->fpst!=NULL ) {
434  for ( i=0; i<sub->fpst->rule_cnt; ++i ) {
435  struct fpst_rule *rule = &sub->fpst->rules[i];
436  for ( j=0; j<rule->lookup_cnt; ++j ) {
437  if ( rule->lookups[j].lookup!=NULL )
438  rule->lookups[j].lookup->in_gpos = true;
439  }
440  }
441  }
442  }
443 }
444 
446  OTLookup *test;
447  struct lookup_subtable *sub;
448  int gpos;
449  AnchorClass *ac;
450  AnchorPoint *ap;
451  SplineChar *sc;
452  KernPair *kp;
453  PST *pst;
454  int i,k,gid,isv;
455  SplineFont *_sf = sf;
456  Justify *jscripts;
457  struct jstf_lang *jlangs;
458 
459  if ( _sf->cidmaster ) _sf = _sf->cidmaster;
460 
461  /* Some things are obvious. If a subtable consists of a kernclass or some */
462  /* such, then obviously it is used. But more distributed info takes more */
463  /* work. So mark anything easy as used, and anything difficult as unused */
464  /* We'll work on the difficult things later */
465  for ( gpos=0; gpos<2; ++gpos ) {
466  for ( test = gpos ? _sf->gpos_lookups : _sf->gsub_lookups; test!=NULL; test = test->next ) {
467  for ( sub = test->subtables; sub!=NULL; sub=sub->next ) {
468  if ( sub->kc!=NULL || sub->fpst!=NULL || sub->sm!=NULL ) {
469  sub->unused = false;
470  continue;
471  }
472  sub->unused = true;
473  /* We'll turn the following bit back on if there turns out */
474  /* to be an anchor class attached to it -- that is subtly */
475  /* different than being unused -- unused will be set if all */
476  /* acs are unused, this bit will be on if there are unused */
477  /* classes that still refer to us. */
478  sub->anchor_classes = false;
479  }
480  }
481  }
482 
483  /* To be useful an anchor class must have both at least one base and one mark */
484  /* (for cursive anchors that means at least one entry and at least one exit) */
485  /* Start by assuming the worst */
486  for ( ac = _sf->anchor; ac!=NULL; ac=ac->next )
487  ac->has_mark = ac->has_base = false;
488 
489  /* Ok, for each glyph, look at all lookups (or anchor classes) it affects */
490  /* and mark the appropriate parts of them as used */
491  k = 0;
492  do {
493  sf = _sf->subfontcnt==0 ? _sf : _sf->subfonts[k];
494  for ( gid=0; gid<sf->glyphcnt; ++gid ) if ( SCWorthOutputting(sc = sf->glyphs[gid]) ) {
495  for ( ap=sc->anchor; ap!=NULL; ap=ap->next ) {
496  switch ( ap->type ) {
497  case at_mark: case at_centry:
498  ap->anchor->has_mark = true;
499  break;
500  case at_basechar: case at_baselig: case at_basemark:
501  case at_cexit:
502  ap->anchor->has_base = true;
503  break;
504  default:
505  break;
506  }
507  }
508  for ( isv=0; isv<2; ++isv ) {
509  for ( kp= isv ? sc->kerns : sc->vkerns ; kp!=NULL; kp=kp->next ) {
510  if ( SCWorthOutputting(kp->sc))
511  kp->subtable->unused = false;
512  }
513  }
514  for ( pst=sc->possub; pst!=NULL; pst=pst->next ) {
515  if ( pst->subtable==NULL )
516  continue;
517  if ( !PSTValid(sf,pst))
518  continue;
519  pst->subtable->unused = false;
520  }
521  }
522  ++k;
523  } while ( k<_sf->subfontcnt );
524 
525  /* Finally for any anchor class that has both a mark and a base then it is */
526  /* used, and its lookup is also used */
527  /* Also, even if unused, as long as the anchor class exists we must keep */
528  /* the subtable around */
529  for ( ac = _sf->anchor; ac!=NULL; ac=ac->next ) {
530  if ( ac->subtable==NULL )
531  continue;
532  ac->subtable->anchor_classes = true;
533  if ( ac->has_mark && ac->has_base )
534  ac->subtable->unused = false;
535  }
536 
537  /* Now for each lookup, a lookup is unused if ALL subtables are unused */
538  for ( gpos=0; gpos<2; ++gpos ) {
539  for ( test = gpos ? _sf->gpos_lookups : _sf->gsub_lookups; test!=NULL; test = test->next ) {
540  test->unused = test->empty = true;
541  for ( sub=test->subtables; sub!=NULL; sub=sub->next ) {
542  if ( !sub->unused )
543  test->unused = false;
544  if ( !sub->unused && !sub->anchor_classes ) {
545  test->empty = false;
546  break;
547  }
548  }
549  }
550  }
551 
552  /* I store JSTF max lookups in the gpos list because they have the same */
553  /* format. But now I need to tease them out and learn which lookups are */
554  /* used in GPOS and which in JSTF (and conceivably which get duplicated */
555  /* and placed in both) */
556  for ( test = sf->gpos_lookups; test!=NULL; test = test->next ) {
557  test->only_jstf = test->in_jstf = test->in_gpos = false;
558  if ( test->features!=NULL )
559  test->in_gpos = true;
560  }
561  for ( jscripts = sf->justify; jscripts!=NULL; jscripts=jscripts->next ) {
562  for ( jlangs=jscripts->langs; jlangs!=NULL; jlangs=jlangs->next ) {
563  for ( i=0; i<jlangs->cnt; ++i ) {
564  struct jstf_prio *prio = &jlangs->prios[i];
565  if ( prio->enableShrink!=NULL )
566  for ( k=0; prio->enableShrink[k]!=NULL; ++k )
567  prio->enableShrink[k]->in_gpos = true;
568  if ( prio->disableShrink!=NULL )
569  for ( k=0; prio->disableShrink[k]!=NULL; ++k )
570  prio->disableShrink[k]->in_gpos = true;
571  if ( prio->enableExtend!=NULL )
572  for ( k=0; prio->enableExtend[k]!=NULL; ++k )
573  prio->enableExtend[k]->in_gpos = true;
574  if ( prio->disableExtend!=NULL )
575  for ( k=0; prio->disableExtend[k]!=NULL; ++k )
576  prio->disableExtend[k]->in_gpos = true;
577  if ( prio->maxShrink!=NULL )
578  for ( k=0; prio->maxShrink[k]!=NULL; ++k )
579  prio->maxShrink[k]->in_jstf = true;
580  if ( prio->maxExtend!=NULL )
581  for ( k=0; prio->maxExtend[k]!=NULL; ++k )
582  prio->maxExtend[k]->in_jstf = true;
583  }
584  }
585  }
586  for ( test = sf->gpos_lookups; test!=NULL; test = test->next ) {
587  if ( test->in_gpos && (test->lookup_type==gpos_context || test->lookup_type==gpos_contextchain))
589  }
590  for ( test = sf->gpos_lookups; test!=NULL; test = test->next )
591  test->only_jstf = test->in_jstf && !test->in_gpos;
592 }
593 
595  int isgpos;
596  OTLookup *otl;
597  struct lookup_subtable *sub;
598 
599  if ( sf->cidmaster ) sf = sf->cidmaster;
600 
601  if ( name==NULL )
602 return( NULL );
603 
604  for ( isgpos=0; isgpos<2; ++isgpos ) {
605  for ( otl = isgpos ? sf->gpos_lookups : sf->gsub_lookups ; otl!=NULL; otl=otl->next ) {
606  for ( sub = otl->subtables; sub!=NULL; sub=sub->next ) {
607  if ( strcmp(name,sub->subtable_name)==0 )
608 return( sub );
609  }
610  }
611  }
612 return( NULL );
613 }
614 
617  free(name);
618 return( sub );
619 }
620 
622  int isgpos;
623  OTLookup *otl;
624 
625  if ( sf->cidmaster ) sf = sf->cidmaster;
626 
627  if ( name==NULL )
628 return( NULL );
629 
630  for ( isgpos=0; isgpos<2; ++isgpos ) {
631  for ( otl = isgpos ? sf->gpos_lookups : sf->gsub_lookups ; otl!=NULL; otl=otl->next ) {
632  if ( strcmp(name,otl->lookup_name)==0 )
633 return( otl );
634  }
635  }
636 return( NULL );
637 }
638 
639 struct scriptlanglist *SLCopy(struct scriptlanglist *sl) {
640  struct scriptlanglist *newsl;
641 
642  newsl = chunkalloc(sizeof(struct scriptlanglist));
643  *newsl = *sl;
644  newsl->next = NULL;
645 
646  if ( sl->lang_cnt>MAX_LANG ) {
647  newsl->morelangs = malloc((newsl->lang_cnt-MAX_LANG)*sizeof(uint32));
648  memcpy(newsl->morelangs,sl->morelangs,(newsl->lang_cnt-MAX_LANG)*sizeof(uint32));
649  }
650 return( newsl );
651 }
652 
654  struct scriptlanglist *head=NULL, *last=NULL, *cur;
655 
656  for ( ; sl!=NULL; sl=sl->next ) {
657  cur = SLCopy(sl);
658  if ( head==NULL )
659  head = cur;
660  else
661  last->next = cur;
662  last = cur;
663  }
664 return( head );
665 }
666 
668  FeatureScriptLangList *newfl;
669 
670  if ( fl==NULL )
671 return( NULL );
672 
673  newfl = chunkalloc(sizeof(FeatureScriptLangList));
674  *newfl = *fl;
675  newfl->next = NULL;
676 
677  newfl->scripts = SListCopy(fl->scripts);
678 return( newfl );
679 }
#define sc
Definition: aptex-macros.h:57
#define name
static point_t cur
Definition: backend_eps.c:108
#define ap
#define free(a)
Definition: decNumber.cpp:310
void glyphs(int opcode)
Definition: disdvi.c:775
int strcmp()
Definition: coll.cpp:143
#define MAX_LANG
Definition: fc-lang.c:259
const FcChar8 lang[6]
Definition: fcfreetype.c:56
#define _(String)
Definition: ftxerr18.c:64
#define memcpy(d, s, n)
Definition: gsftopk.c:64
#define NULL
Definition: ftobjs.h:61
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
voidp calloc()
static int ret
Definition: convert.c:72
#define malloc
Definition: alloca.c:91
#define test
Definition: tie.c:129
unsigned long uint32
Definition: tiff.h:68
unsigned char uint8
Definition: tiff.h:60
#define qsort
Definition: includes.h:72
#define realloc
Definition: glob.c:206
list langs
Definition: fc-lang.py:152
static const Mapping features[]
Definition: otfdescrip.cc:537
int k
Definition: otp-parser.c:70
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld[DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
set set set set set set set set set set set set set set set set set set set set *set set set macro pixldst op &r &cond WK op &r &cond WK op &r &cond WK else op &m &cond &ia op &r &cond WK else op &m &cond &ia elseif elseif else error unsupported base if elseif elseif else error unsupported unaligned pixldst unaligned endm macro pixst base base else pixldst base endif endm macro PF base if bpp PF set rept prefetch_distance PF set OFFSET endr endif endm macro preload_leading_step2 base if bpp ifc DST PF PF else if bpp lsl PF PF lsl PF sub
static int cnt
Definition: pkout.c:166
static int32_t last
Definition: ppagelist.c:29
int g
Definition: ppmqvga.c:68
SplineChar * SFGetChar(SplineFont *sf, int unienc, const char *name)
Definition: fvfonts.c:175
int SFFindExistingSlot(SplineFont *sf, int unienc, const char *name)
Definition: fvfonts.c:246
SplineChar ** SFGlyphsWithPSTinSubtable(SplineFont *sf, struct lookup_subtable *subtable)
Definition: lookups.c:370
struct lookup_subtable * SFFindLookupSubtableAndFreeName(SplineFont *sf, char *name)
Definition: lookups.c:615
static void TickLookupKids(OTLookup *otl)
Definition: lookups.c:428
static int uint32_cmp(const void *_ui1, const void *_ui2)
Definition: lookups.c:30
static int LigaturesFirstComponentGID(SplineFont *sf, char *components)
Definition: lookups.c:327
static int PSTValid(SplineFont *sf, PST *pst)
Definition: lookups.c:338
OTLookup ** SFLookupsInScriptLangFeature(SplineFont *sf, int gpos, uint32 script, uint32 lang, uint32 feature)
Definition: lookups.c:282
uint32 * SFFeaturesInScriptLang(SplineFont *sf, int gpos, uint32 script, uint32 lang)
Definition: lookups.c:195
static int lang_cmp(const void *_ui1, const void *_ui2)
Definition: lookups.c:39
uint32 * SFLangsInScript(SplineFont *sf, int gpos, uint32 script)
Definition: lookups.c:132
FeatureScriptLangList * FeatureListCopy(FeatureScriptLangList *fl)
Definition: lookups.c:667
struct lookup_subtable * SFFindLookupSubtable(SplineFont *sf, char *name)
Definition: lookups.c:594
uint32 * SFScriptsInLookups(SplineFont *sf, int gpos)
Definition: lookups.c:55
struct scriptlanglist * SListCopy(struct scriptlanglist *sl)
Definition: lookups.c:653
OTLookup * SFFindLookup(SplineFont *sf, char *name)
Definition: lookups.c:621
void SFFindUnusedLookups(SplineFont *sf)
Definition: lookups.c:445
struct scriptlanglist * SLCopy(struct scriptlanglist *sl)
Definition: lookups.c:639
@ pst_pair
Definition: splinefont.h:563
@ pst_multiple
Definition: splinefont.h:565
@ pst_position
Definition: splinefont.h:563
@ pst_alternate
Definition: splinefont.h:564
@ pst_substitution
Definition: splinefont.h:564
@ pst_ligature
Definition: splinefont.h:565
@ gpos_context
Definition: splinefont.h:370
@ gsub_ligature
Definition: splinefont.h:352
@ gpos_contextchain
Definition: splinefont.h:371
@ gpos_pair
Definition: splinefont.h:365
#define DEFAULT_LANG
Definition: splinefont.h:340
@ at_cexit
Definition: splinefont.h:513
@ at_baselig
Definition: splinefont.h:513
@ at_mark
Definition: splinefont.h:513
@ at_basechar
Definition: splinefont.h:513
@ at_basemark
Definition: splinefont.h:513
@ at_centry
Definition: splinefont.h:513
#define chunkalloc(size)
Definition: splinefont.h:1947
#define LogError
Definition: uiinterface.h:125
test
Definition: parser.c:257
#define SCWorthOutputting(a)
Definition: splinefont.h:2357
struct anchorclass * next
Definition: splinefont.h:510
struct lookup_subtable * subtable
Definition: splinefont.h:505
uint8 has_base
Definition: splinefont.h:507
uint8 has_mark
Definition: splinefont.h:508
struct featurescriptlanglist * next
Definition: splinefont.h:417
struct scriptlanglist * scripts
Definition: splinefont.h:416
unsigned int ismac
Definition: splinefont.h:418
struct generic_pst::@1432::@1435 mult
struct splinechar * lig
Definition: splinefont.h:595
uint8 type
Definition: splinefont.h:587
struct lookup_subtable * subtable
Definition: splinefont.h:588
char * paired
Definition: splinefont.h:592
char * components
Definition: splinefont.h:594
struct generic_pst::@1432::@1433 pair
union generic_pst::@1432 u
struct generic_pst * next
Definition: splinefont.h:589
Definition: ttf.h:354
struct jstf_lang * next
Definition: splinefont.h:725
struct jstf_prio * prios
Definition: splinefont.h:727
OTLookup ** enableShrink
Definition: splinefont.h:715
OTLookup ** enableExtend
Definition: splinefont.h:718
OTLookup ** maxExtend
Definition: splinefont.h:720
OTLookup ** disableExtend
Definition: splinefont.h:719
OTLookup ** maxShrink
Definition: splinefont.h:717
OTLookup ** disableShrink
Definition: splinefont.h:716
struct jstf_script * next
Definition: splinefont.h:732
struct jstf_lang * langs
Definition: splinefont.h:734
Definition: ttf.h:392
struct otlookup * lookup
Definition: splinefont.h:429
unsigned int anchor_classes
Definition: splinefont.h:432
unsigned int unused
Definition: splinefont.h:430
unsigned int in_gpos
Definition: splinefont.h:473
struct otlookup * next
Definition: splinefont.h:458
struct lookup_subtable * subtables
Definition: splinefont.h:463
char * lookup_name
Definition: splinefont.h:461
enum otlookup_type lookup_type
Definition: splinefont.h:459
unsigned int in_jstf
Definition: splinefont.h:474
Definition: rule.h:21
struct scriptlanglist * next
Definition: splinefont.h:408
uint32 langs[4]
Definition: splinefont.h:405
uint32 * morelangs
Definition: splinefont.h:406
Definition: tfmaux.c:31
OTLookup * gpos_lookups
Definition: splinefont.h:1760
struct splinefont * cidmaster
Definition: splinefont.h:1739
struct splinefont ** subfonts
Definition: splinefont.h:1738
AnchorClass * anchor
Definition: splinefont.h:1762
int subfontcnt
Definition: splinefont.h:1737
OTLookup * gsub_lookups
Definition: splinefont.h:1760
#define CHR(x)
Definition: sysdep.h:200
ch
Definition: t4ht.c:1443
int j
Definition: t4ht.c:1589
found
Definition: tex4ht.c:5000
@ start
Definition: preamble.c:52
PATTERN * pt
Definition: vlna.c:74